2012-11-08 48 views
34

我的工作最近涉及編程製作視頻。在Python中,典型的工作流程看起來是這樣的:你可以「流」圖像到ffmpeg構建一個視頻,而不是將它們保存到磁盤?

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。

+8

我不知道如何創建圖像,但ffmpeg也接受管道輸入:'ffmpeg -f image2pipe -c:v png -r 30000/1001 -i -'。 – LordNeckbeard

+0

爲簡單起見,假設'createFrame(i)'返回一個Python圖像庫圖像對象,我們將它存儲在'img'中。我認爲你的迴應是朝着正確方向邁出的一步,但挑戰的一半是在python程序中將構建的圖像傳輸到ffmpeg。 – Brandon

+0

也許隊列,然後通過第二個線程管圖像? – lolopop

回答

49

好吧我得到它的工作。感謝LordNeckbeard建議使用image2pipe。我不得不使用jpg編碼而不是png because image2pipe with png doesn't work on my verision of ffmpeg。第一個腳本與您的問題代碼基本相同,除了我實現了一個簡單的圖像創建,只創建從黑色到紅色的圖像。我還添加了一些代碼來定時執行。

串行執行

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倍。

+0

太棒了!我已經測試過了,它的功能非常好。 – Brandon

+16

對於任何在將來遇到此問題的人來說,用'PNG'替換'png'和'JPEG'的'mjpeg'爲我使用png。 – Brandon

+0

儘管文件大小是x4 – bluesummers