使用 Python 子进程通过管道传输到 FFMPEG 时冻结

2023-11-26

通过以下代码,我可以使用 Python、Numpy 和 FFMPEG 二进制文件将视频帧传输到 FFMPEG:

from __future__ import print_function
import subprocess
import numpy as np
import sys

npshape = [480, 480]
cmd_out = ['ffmpeg',
           '-y', # (optional) overwrite output file if it exists
           '-f', 'rawvideo',
           '-vcodec','rawvideo',
           '-s', '%dx%d'%(npshape[1], npshape[0]), # size of one frame
           '-pix_fmt', 'rgb24',
           '-r', '24', # frames per second
           '-i', '-', # The input comes from a pipe
           '-an', # Tells FFMPEG not to expect any audio
           '-vcodec', 'mpeg4',
           'output.mp4']

fout = subprocess.Popen(cmd_out, stdin=subprocess.PIPE, stderr=subprocess.PIPE).stdin

for i in range(24*40):
    if i%(24)==0: 
        print('%d'%(i/24), end=' ')
        sys.stdout.flush()

    fout.write((np.random.random(npshape[0]*npshape[1]*3)*128).astype('uint8').tostring())

fout.close()

如果我编写任何少于 37 秒的帧,则效果很好,但如果我尝试编写更多内容,代码就会挂起。这种行为的根本原因是什么?我该如何修复它?


罪魁祸首很可能是令人作呕的恶臭subprocess.Popen线。您不仅忽略它的返回值 - 您绝对不能这样做,以确保子进程在某个点完成和/或检查其退出代码 - 您还可以stderr一个管道但从未读取它 - 因此当缓冲区填满时进程必须挂起。

这应该可以修复它:

p = subprocess.Popen(cmd_out, stdin=subprocess.PIPE)
fout = p.stdin

<...>

fout.close()
p.wait()
if p.returncode !=0: raise subprocess.CalledProcessError(p.returncode,cmd_out)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Python 子进程通过管道传输到 FFMPEG 时冻结 的相关文章

随机推荐