2009-09-21 14 views
8

मैं FFMPEG के लिए एक gui लिखने की कोशिश कर रहा हूं। मैं अपने इच्छित रूपांतरण के लिए ffmpeg प्रक्रिया बनाने के लिए अजगर उपप्रोसेस का उपयोग कर रहा हूं। यह ठीक काम करता है, लेकिन मैं यह भी रूपांतरण की प्रगति प्राप्त करने के लिए एक तरह से करना चाहते हैं, चाहे वह विफल रहा है या नहीं आदि मैं सोचा मैं बहुत तरह की प्रक्रिया के stdout तक पहुंच कर इस कर सकता है:एफएफएमपीईजी और पायथन उपप्रोसेसर

subprocess.Popen()

कॉलिंग
# Convert - Calls FFMPEG with current settings. (in a seperate 
# thread.) 
def convert(self): 
    # Check if options are valid 
    if self.input == "" or self.output == "": 
     return False 

# Make the command string 
ffmpegString = self.makeString() 

# Try to open with these settings 
try: 
    self.ffmpeg = subprocess.Popen(ffmpegString, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 
except OSError: 
    self.error.append("OSError: ") 
except ValueError: 
    self.error.append("ValueError: Couldn't call FFMPEG with these parameters") 

# Convert process should be running now. 

और stdout पढ़ने:

convert = Convert() 
convert.input = "test.ogv" 
convert.output = "test.mp4" 
convert.output_size = (0, 0) 

convert.convert() 

while 1: 
    print convert.ffmpeg.stdout.readline() 

यह काम करता है लेकिन, ffmpeg की स्थिति नहीं दिखाती है। मुझे लगता है कि ffmpeg इसे रीफ्रेश करने के तरीके के साथ कुछ करना है। क्या इसका उपयोग करने का कोई तरीका है?

उत्तर

8

मुझे अक्सर हारने के लिए कठिन मुद्दों के कारण, मानक प्रसंस्करण (या यहां तक ​​कि मानक त्रुटि!) को उपप्रोसेसर के साथ पढ़ने में समस्याएं देखी गई हैं। मेरा पसंदीदा समाधान, जब मुझे उपप्रोसेसर से इस तरह के स्टडआउट/स्टडर को पढ़ने की आवश्यकता होती है, तो subprocess, pexpect (या, विंडोज़, wexpect पर) के बजाय, उपयोग करने के लिए स्विच करना है।

+0

आपके दोनों लिंक मर चुके हैं, कृपया उन्हें ठीक करें। – slhck

-1

FFMPEG:

FFMPEG उत्पादन सभी स्थिति पाठ stderr इंटरफेस पर (जो आप देखते हैं जब आप इसे मैन्युअल रूप से कमांड लाइन पर चलने)। Ffmpeg से आउटपुट कैप्चर करने के लिए, आपको stderr इंटरफ़ेस को देखना होगा - या इसे उदाहरण की तरह रीडायरेक्ट करना होगा। stderr पर उत्पादन के लिए

की जांच:

यहाँ एक और तरीका कोशिश करते हैं और बजाय इसे पुन: निर्देशित होने, stderr से पढ़ने के लिए जब popen

Popen class अजगर में stderr नामक एक फ़ाइल वस्तु है बुला है , आप इसे उसी तरह एक्सेस करेंगे जैसे आप stdout तक पहुंच रहे हैं। मैं अपने पाश कुछ इस तरह दिखेगा सोच रहा हूँ:

while 1: 
    print convert.ffmpeg.stdout.readline() 
    print convert.ffmpeg.stderr.readline() 

अस्वीकरण: मैं अजगर में इस परीक्षण नहीं किया है, लेकिन मैं जावा का उपयोग कर एक तुलनीय आवेदन किया।

+0

वह पहले से ही stderr को stdout पर रीडायरेक्ट कर रहा है। –

+0

गोर्गापोर, क्या आप वाकई हैं? –

+0

हां, stderr को उप-प्रोसेस के साथ लाइन पर कोड स्निपिट में रीडायरेक्ट किया जाता है। पोपेन - निश्चित रूप से इसे काट दिया जा सकता है यदि आप कोड स्निपिट के नीचे स्क्रॉल बार का उपयोग नहीं करते हैं ... –

3

मुझे लगता है कि आप रीडलाइन का उपयोग नहीं कर सकते क्योंकि ffmpeg कभी भी एक पंक्ति मुद्रित नहीं करता है, स्थिति \ r (carrige वापसी) लिखकर और फिर लाइन को फिर से लिखकर अपडेट किया जाता है।

size=  68kB time=0.39 bitrate=1412.1kbits/s \rsize= 2786kB time=16.17 bitrate=1411.2kbits/s \rsize= 5472kB time=31.76 bitrate=1411.2kbits/s \r\n 

आप पंक्ति के ऊपर आप ध्यान देंगे है कि वहाँ केवल एक ही \ N और कहा कि जब फ़ाइल परिवर्तित किया जाता है प्रिंट हो जांच-पड़ताल करें।

+1

आप रीडलाइन कर सकते हैं, लेकिन इसे समाप्त होने के बाद ही आपको उस पंक्ति का अंतिम संस्करण मिलता है ... – Anentropic

2

चूंकि ffmpeg stderr के लिए unflushed डेटा लिखता है, तो आपको fcntl का उपयोग करके गैर-अवरुद्ध करने के लिए stderr फ़ाइल डिस्क्रिप्टर सेट करना होगा।

 
    fcntl.fcntl(
     pipe.stderr.fileno(), 
     fcntl.F_SETFL, 
     fcntl.fcntl(pipe.stderr.fileno(), fcntl.F_GETFL) | os.O_NONBLOCK, 
    ) 

और फिर पाश पूर्ण उदाहरण के लिए डेटा

 
    while True: 
     readx = select.select([pipe.stderr.fileno()], [], [])[0] 
     if readx: 
      chunk = pipe.stderr.read() 

पढ़ने के लिए चयन का उपयोग कर here जाना।

+0

मुझे यकीन नहीं है कि यह अभी भी सत्य है .. मुझे proc.stderr: प्रिंट लाइन proc.stderr.flush() ' – Anentropic

+0

आह नहीं, ठीक है, ठीक है, fm2.7: पर ffmpeg के वर्तमान निर्माण में stderr पर एक रीडलाइन कर रहा है। मुझे एन्कोडिंग के दौरान 'फ्रेम = xxx' स्थिति आउटपुट के प्रगतिशील आउटपुट नहीं मिल रहे हैं (क्योंकि यह एक पंक्ति है जो बार-बार अपडेट हो जाती है) लेकिन मुझे मेटाडेटा एल दिखाई देता है। इनस तब तक अवरुद्ध हो जाता है जब तक कि एन्कोडिंग समाप्त न हो जाए, केवल अंतिम स्थिति अपडेट दिखा रहा हो, फिर यह शेष सारांश रेखाएं दिखाता है। – Anentropic

5

बस जोड़ें, universal_newlines = अपने subprocess.Popen लाइन के लिए सही है।

frame= 1900 fps=453 q=18.6 Lsize= 3473kB time=00:01:16.08 bitrate= 373.9kbits/s 

उपयोग समय = मूल्य प्रतिशत में प्रगति निर्धारित करने के लिए:

cmd="ffmpeg -i in.mp4 -y out.avi" 
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,universal_newlines=True) 
for line in process.stdout: 
    print(line) 

के लिए अब आप लाइन चक्र में की तरह मिल गया।

+0

दिलचस्प समाधान, लेकिन Popen के साथ कुछ बफरिंग मुद्दों को जोड़ें। यदि आप लाइव एन्कोडिंग निगरानी की तलाश में हैं तो सीधे बॉक्स से बाहर काम नहीं करेंगे। – littlebridge

-2
ffmpegCommand=''' 
ffmpeg 
-f lavfi 
-i anullsrc=channel_layout=1c:sample_rate=11025 
-rtsp_transport tcp 
-rtsp_transport udp 
-rtsp_transport http 
-thread_queue_size 32000 
-i rtsp://xxx.xxx.xxx.xxx:554/user=admin&password=xxx&channel=1&stream=1.sdp?real_stream 
-reconnect 1 
-reconnect_at_eof 1 
-reconnect_streamed 1 
-reconnect_delay_max 4294 
-tune zerolatency 
-c:v copy 
-c:a aac 
-bufsize 6000k 
-f flv rtmp://a.rtmp.youtube.com/live2/xxx-xxx-xxx-xxx''' 
cmd=ffmpegCommand.split() 
# "universal newline support" This will cause to interpret \n, \r\n and \r  equally, each as a newline. 

p = subprocess.Popen(cmd, stderr=subprocess.PIPE, universal_newlines=True) 
while True:  
     print(p.stderr.readline().rstrip('\r\n')) 
संबंधित मुद्दे