2009-09-21 7 views
8

FFMPEG에 대한 GUI를 작성하려고합니다. 내가 원하는 모든 변환에 대해 ffmpeg 프로세스를 생성하기 위해 pythons 하위 프로세스를 사용하고 있습니다. 이것은 잘 작동하지만 나는 또한 내가과 같이 프로세스의 표준 출력에 액세스하여이 작업을 수행 할 수있는 생각 등 실패 여부, 변환의 진행을 얻을 수있는 방법을 싶습니다FFMPEG 및 Python 보조 프로세스

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

저는 패배하기 어려운 버퍼링 문제로 인해 하위 프로세스로 표준 출력 (또는 표준 오류!)을 읽는 데 문제가 있음을 종종 눈치 챘습니다. 내가 좋아하는 해결책은, 하위 프로세스에서 stdout/stderr을 읽을 필요가있을 때 subprocess, pexpect (또는 Windows에서는 wexpect) 대신 사용으로 전환하는 것입니다.

+0

두 링크가 모두 죽었으니 수정하십시오 – slhck

-1

FFMPEG 다음 표준 에러 인터페이스 (명령 행에서 수동으로 실행할 때 표시)

FFMPEG 출력 모든 상태 텍스트. ffmpeg에서 출력을 캡처하려면 stderr 인터페이스를 보거나 예제와 같이 리디렉션해야합니다. 표준 에러에 출력

확인 : 여기

파이썬의 Popen class 열려진라는 파일 개체가

을는 popen를 호출 할 때 시도하고 대신 리디렉션의, 표준 에러에서 읽을 수있는 또 다른 방법입니다 , 당신은 stdout에 접근하는 것과 같은 방법으로 접근 할 수 있습니다. 내가 파이썬에서이 테스트를하지 않은,하지만 난 자바를 사용하여 비교 응용 프로그램을 만든 :

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

면책 조항 : 나는 당신의 루프는 다음과 같이 보일 것이라고 생각하고있다.

+0

그는 이미 stderr을 stdout으로 리디렉션하고 있습니다. –

+0

Gorgapor, 그가 틀림없는가요? –

+0

예, stderr는 subprocess.Popen이있는 행의 코드 조각에서 리디렉션됩니다. 물론 코드 스 니핏 아래에서 스크롤 막대를 사용하지 않으면 잘릴 수 있습니다. –

3

ffmpeg가 한 줄을 인쇄하지 않기 때문에 readline을 사용할 수 없다고 생각합니다. \ r (carrige return)을 쓰고 상태를 다시 작성하여 상태가 업데이트됩니다.

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

당신은 readline을 할 수 있지만 완료되면 해당 라인의 최종 버전 만 얻습니다 ... – Anentropic

2

ffmpeg는 unflushed 데이터를 stderr에 쓰므로 stderr 파일 설명자를 fcntl을 사용하여 non-blocking으로 설정해야합니다. here를 이동 전체 예를 들어, 데이터

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

을 읽을 선택하여

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

다음 루프.

+0

이것이 여전히 사실인지 확실하지 않습니다. . 진보적 인 출력을 py2.7의 ffmpeg의 현재 빌드에서 stderr의 readline으로 처리한다 : 'for proc.stderr : 인쇄 라인 proc.stderr.flush()' – Anentropic

+0

ah no, well, sort 인코딩 중에'frame = xxx' 상태 출력을 점진적으로 출력하지는 않습니다. (이것은 반복적으로 업데이트되는 한 줄이기 때문에) 메타 데이터 l을 봅니다. 그런 다음 인코딩이 완료 될 때까지 차단하고 마지막 상태 업데이트 만 표시 한 다음 나머지 요약 행을 표시합니다. – Anentropic

5

보편적으로 universal_newlines = 귀하의 하위 프로세스에 True를 추가하십시오.

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')) 
관련 문제