音声付動画を再生するためのちょうど良いプログラムの書き方例がネット上で意外と見当たらない。 単に動画を再生するだけじゃなくて動画の各フレームに対して画像処理できるようにOpenCVで画像を扱いたい。 mp4動画だけならOpenCVで簡単に再生できる。音声はmp4からwaveに変換しておいてwaveをPyAudioで再生する。 動画と音声をスレッドで独立に再生させると音ズレの問題があるので、 動画もフレーム単位で、音声はチャンク(一定数のフレーム)単位で再生して、動画の再生後の経過時間とフレーム番号の同期を取る。 音声は特に処理するつもりはないので、遅れたりしないものとしてる(というか、同期とる方法を知らないだけ)。
ライブラリとグローバル変数
必要なライブラリはこれだけ.唯一のグローバル変数はflagで,動画再生スレッドが終了したと同時に音声再生スレッドを終了させるために用いる.
import cv2 import pyaudio import wave import threading import time flag = True
音声再生用の関数
チャンクのサイズはchunk=1024フレーム. while文でflagがFalseになるまで再生し続ける.
def play_audio(fname): wf = wave.open(fname, "rb") p = pyaudio.PyAudio() stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),\ channels=wf.getnchannels(),\ rate=wf.getframerate(), output=True) chunk = 1024 data = wf.readframes(chunk) #flagがFalseになるとループを抜ける while data != '' and flag: #ここで再生している stream.write(data) data = wf.readframes(chunk) stream.stop_stream() stream.close() p.terminate()
動画再生用の関数
動画再生時のポイントは,while文の中の最初のif文. CAP_PROP_POS_MSECで再生中動画フレームに対応した時間を取得できるので, これとPCの時間とを比較して動画再生が早すぎると空回りするようになっている. もうちっとシンプルに書けるかも.一応これでパット見スムーズに再生される.
def play_video(fname): global flag window_name = "PlayVideoAudio" cap = cv2.VideoCapture(fname) start = time.time() if not cap.isOpened(): sys.exit() while True: elapsed_time = (time.time() - start)*1000 play_time = int(cap.get(cv2.CAP_PROP_POS_MSEC)) if elapsed_time < play_time: key = cv2.waitKey(1) if key == 27: global flag flag = False break else: continue else: ret, frame = cap.read() if ret: cv2.imshow(window_name, frame) else: flag = False break
ここからが実行部分
これがメインスレッド.このプログラムの欠点は, mp4に音声が含まれているのにmp4とwavを両方準備しないといけないこと. あとは,エラーで停止すると音声再生スレッドがゾンビ化する. 例外処理などもちゃんとしないといけない.
audio_file = "test.wav" video_file = "test.mp4" thread1 = threading.Thread(target=play_audio, args=[audio_file]) thread2 = threading.Thread(target=play_video, args=[video_file]) thread1.start() thread2.start() thread1.join() thread2.join()
PyAudioのインストール方法
上記のプログラムを実行するには予めPyAudioのインストールが必要. pyaudioはwindowsでpipを使うと上手くインストールできない.対処法は, ここからPyAudio-0.2.11-cp37-cp37m-win_amd64.whlをダウンロードして次のコマンドなどでインストールする.
pip install PyAudio-0.2.11-cp37-cp37m-win_amd64.whl
cp37の部分がpythonのバージョン3.7に対応しているので自分の環境のバージョンに合わせてファイルを選択する必要がある.