PythonのMoviePyモジュールの進捗具合をリアルタイムにPHPに返却したい

実現したいこと

PythonのMoviePyモジュールの進捗具合をリアルタイムにPHPに返却したいのに、処理が完了してから一度に返却されてしまう。

前提

ウェブサーバーにPHPファイルを配置し、クラウド上に配置したPythonファイルにリクエストを送信します。PHP側はPythonとtext/event-streamでリアルタイムにレスポンスを受け取ることができる状態にあることを確認済みです。

発生している問題・エラーメッセージ

リアルタイムに欲しいのに、全部完了してから返却される
ここで、Pythonのmoviepyモジュールを使用して動画を処理し、その進捗状況をリアルタイムにPHP側に返却するコードを考えています。現状、「すべての処理が完了してから結果がまとめてPythonから返却される」状態になってしまっており、リアルタイムに出力できていません。

質問事項
以下のコードで「リアルタイムに進捗状況を返却する」という要件を達成するにはどのようにすればいいでしょうか?
※抜本的に違う方法を使うというのでも良いのですが、現状のコードをできるだけ活用したいと思っています。

該当のソースコード

Python

1import os 2from flask import *3from moviepy.video.io.VideoFileClip import VideoFileClip 4from proglog import ProgressBarLogger 5 6app = Flask(__name__)7 8@app.route('/', methods=['GET', 'POST'])9def main():10 11 #動画データのファイルパスを指定します。本来はPHPからのリクエストにファイルパスを指定する記述がありますが今回は割愛します12 originalFilePath = f"/path/to/originalFile/"13 processedFilePath = f"/path/to/processedFile/"14 15 with open(originalFilePath, "w") as originalFile, open(processedFilePath, "w") as processedFile:16 videoFile = VideoFileClip(originalFile)17 18 #42行目のwrite_videofile()のloggerにこのクラスを指定しています19 class MyBarLogger(ProgressBarLogger):20 def __init__(self, response):21 super().__init__()22 self.response = response 23 self.last_message = ''24 self.previous_percentage = 025 self.stream_generator = event_stream("initiated")26 27 def callback(self, **changes):28 for (parameter, value) in changes.items():29 self.last_message = value 30 31 def bars_callback(self, bar, attr, value, old_value=None):32 if 'Writing video' in self.last_message:33 percentage = (value / self.bars[bar]['total']) * 10034 if int(percentage) != self.previous_percentage:35 self.previous_percentage = int(percentage)36 result = "data: {0}\n\n".format(self.previous_percentage)37 next(self.stream_generator, None) # Move the generator forward38 self.response.stream.write(result)39 self.response.stream.flush()40 41 logger = MyBarLogger(Response(content_type="text/event-stream"))42 videoFile.subclip(0, 10).write_videofile(processedFile, codec="libx264", logger=logger)43 return logger.response 44 45def event_stream(arg):46 yield "data: {0}\n\n".format(arg)47 48if __name__ == "__main__":49 app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))

試したこと

Printではリアルタイムに値が表示される
36行目などに表示されるresultをprintしてみると、コンソール上でリアルタイムに出力されていることを確認済みです。PHPからのリクエストに対してはリアルタイムに応えられていません。

PHP側に問題はなさそう
また、PHP側でリアルタイムに結果を受け取ることができることを確認すべく、以下のようなコードをPython側に記載してみたところ、リアルタイムに結果が返却されることを確認しました。

#前略 def main(): resp = make_response() resp.headers["Content-Type"] = "text/event-stream" resp.response = sse_make() return resp def sse_make(): for i in range(10): yield "data: {0} {1}".format(str(i),"\n\n") time.sleep(1) pass

補足情報(FW/ツールのバージョンなど)

現状の戻り値は以下の通りです。
write_videofileの処理が完了した後で一度にPHP側に返却されてしまいます。

"data: comp data: 1 data: 2 data: 3 …(1刻みで4~98までが返されます) data: 99 data: comp "

コメントを投稿

0 コメント