2012-11-08 10 views
34

मेरे काम में हाल ही में प्रोग्रामेटिक रूप से वीडियो बनाने शामिल हैं। अजगर में, ठेठ कार्यप्रवाह इस तरह दिखता है:क्या आप डिस्क को सहेजने के बजाय, वीडियो बनाने के लिए 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)' एक पायथन छवि लाइब्रेरी छवि ऑब्जेक्ट देता है, जिसे हम 'img' में संग्रहीत करते हैं। मुझे लगता है कि आपकी प्रतिक्रिया सही दिशा में एक कदम है, लेकिन पाइथन कार्यक्रम में आधा चुनौती निर्मित छवियों को ffmpeg पर पाइप कर देगी। – Brandon

+0

शायद कतार और फिर छवियों को दूसरे धागे के माध्यम से पाइप करें? – lolopop

उत्तर

49

ठीक है, मुझे यह काम मिल गया। Image2pipe का उपयोग करने के लिए लॉर्डनेकबीर्ड सुझाव के लिए धन्यवाद। मुझे png because image2pipe with png doesn't work on my verision of ffmpeg के बजाय 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 गुना तेज है।

+0

शानदार! मैंने इसका परीक्षण किया है और यह आश्चर्यजनक रूप से काम करता है। – Brandon

+16

किसी भी व्यक्ति जो भविष्य में इस पर ठोकर खा रहा है, 'पीजीएन' के साथ 'एमजीपीईजी' और 'जेपीईजी' के साथ 'पीजीजी' के साथ बदलकर मेरे लिए पीएनजी का उपयोग करने के लिए काम किया। – Brandon

+0

मैं '-vcodec png' और' im.save (p.stdin, 'PNG') का उपयोग करके सर्वोत्तम गुणवत्ता प्राप्त करने में कामयाब रहा हूं, हालांकि फाइलसाइज x4 – bluesummers

संबंधित मुद्दे

 संबंधित मुद्दे