我试图写一个GUI FFMPEG
。 我使用蟒蛇子创建每次转换我希望有一个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的方式刷新它。 是否有访问它的方法吗?
Answer 1:
我经常发现有子问题读取标准输出(或甚至标准错误!),由于是很难打败缓冲的问题。 我最喜欢的解决方案,当我需要从子读这样的标准输出/标准错误,是切换到使用,而不是subprocess
, pexpect
(或者,在Windows上, wexpect
)。
Answer 2:
Simply add ,universal_newlines=True to your subprocess.Popen line.
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)
For now you got line in cycle like:
frame= 1900 fps=453 q=18.6 Lsize= 3473kB time=00:01:16.08 bitrate= 373.9kbits/s
Use the time= value to determine progress in percentage.
Answer 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和当文件转换完成,即会打印。
Answer 4:
由于ffmpeg的写入未刷新到stderr数据,你必须设置标准错误文件描述符使用的fcntl无阻塞。
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()
全例如去这里 。
Answer 5:
FFMPEG:
FFMPEG输出的所有状态文本(你所看到的,当你在命令行上手动运行)标准错误接口上。 为了捕捉ffmpeg的输出,你需要看的标准错误界面 - 或重定向像的例子。
检查的标准错误输出:
这里是另一种尝试和标准错误读取,而不是调用POPEN时重定向它,
该POPEN类 Python中有一个叫做标准错误的文件对象,你会访问它在您访问标准输出相同的方式。 我想你的循环会是这个样子:
while 1:
print convert.ffmpeg.stdout.readline()
print convert.ffmpeg.stderr.readline()
免责声明:我没有在Python测试这一点,但我做了使用Java应用程序相媲美。
Answer 6:
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'))
文章来源: FFMPEG and Pythons subprocess