55

私の最近の仕事は、プログラムでビデオを作成することです。Python では、典型的なワークフローは次のようになります。

import subprocess, Image, ImageDraw

for i in range(frames_per_second * video_duration_seconds):
    img = createFrame(i)
    img.save("%07d.png" % i)

subprocess.call(["ffmpeg","-y","-r",str(frames_per_second),"-i", "%07d.png","-vcodec","mpeg4", "-qscale","5", "-r", str(frames_per_second), "video.avi"])

このワークフローは、ビデオのフレームごとに画像を作成し、ディスクに保存します。すべての画像が保存された後、すべての画像からビデオを構築するために ffmpeg が呼び出されます。

画像をディスクに保存する (メモリ内に画像を作成するのではなく) と、ここでのサイクルの大部分が消費され、その必要はないようです。画像をディスクに保存せずに同じ機能を実行する方法はありますか? したがって、ffmpeg が呼び出され、イメージが構築され、構築された直後に ffmpeg に供給されます。

4

3 に答える 3

69

わかりました。動作しました。image2pipe を使用するという LordNeckbeard の提案に感謝します。png を使用した image2pipe は私のバージョンの ffmpeg では機能しないため、pngの代わりに jpg エンコーディングを使用する必要がありました。最初のスクリプトは、黒から赤への画像を作成するだけの単純な画像作成を実装したことを除いて、基本的に質問のコードと同じです。また、実行の時間を計るためにいくつかのコードを追加しました。

シリアル実行

import subprocess, Image

fps, duration = 24, 100
for i in range(fps * duration):
    im = Image.new("RGB", (300, 300), (i, 1, 1))
    im.save("%07d.jpg" % i)
subprocess.call(["ffmpeg","-y","-r",str(fps),"-i", "%07d.jpg","-vcodec","mpeg4", "-qscale","5", "-r", str(fps), "video.avi"])

並列実行 (画像をディスクに保存しない)

import Image
from subprocess import Popen, PIPE

fps, duration = 24, 100
p = Popen(['ffmpeg', '-y', '-f', 'image2pipe', '-vcodec', 'mjpeg', '-r', '24', '-i', '-', '-vcodec', 'mpeg4', '-qscale', '5', '-r', '24', 'video.avi'], stdin=PIPE)
for i in range(fps * duration):
    im = Image.new("RGB", (300, 300), (i, 1, 1))
    im.save(p.stdin, 'JPEG')
p.stdin.close()
p.wait()

結果は興味深いものです。パフォーマンスを比較するために各スクリプトを 3 回実行しました: シリアル:

12.9062321186
12.8965060711
12.9360799789

平行:

8.67797684669
8.57139396667
8.38926696777

ということで、並列版の方が約1.5倍速いようです。

于 2012-11-08T21:58:29.567 に答える