Python实现FFmpeg输出接入管道报错,求正确实现方案
问题:Python调用FFmpeg并将结果写入管道失败
问题背景
有一条可正常运行的Shell命令,用于将FFmpeg处理后的视频流追加到名为push的管道:
ffmpeg -re -i '2023-02-16_21:02:50.mp4' -f mpegts -c:v copy -c:a aac -vbsf h264_mp4toannexb pipe:1.ts | cat >> push
但用Python的subprocess模块实现时,出现错误:
cat: '>>': No such file or directory
对应的Python代码如下:
command = [ 'docker', 'run', '-v', f'{cwd}:{cwd}', '-w', f'{cwd}', 'jrottenberg/ffmpeg', '-re', '-i', f'{video_path}', '-f', 'mpegts', '-c:v', 'copy', '-c:a', 'aac', '-vbsf', 'h264_mp4toannexb', 'pipe:1.ts', ] pa = subprocess.Popen( command, stdout = subprocess.PIPE, stderr = error_file ) command = [ 'cat', '>>', f'{pipe_name}' ] with pa.stdout: pb = subprocess.Popen( command, stdin = pa.stdout, stdout = error_file, stderr = error_file )
错误原因
>>是Shell的重定向语法,不是cat命令的参数。当你把>>放进subprocess的命令列表时,cat会将其视为要读取的文件名,自然找不到这个文件,从而报错。
解决方案
方案1:跳过cat,直接用Python写入管道
这是最安全且高效的方式,不需要依赖Shell的重定向,直接在Python中处理FFmpeg的输出:
command = [ 'docker', 'run', '-v', f'{cwd}:{cwd}', '-w', f'{cwd}', 'jrottenberg/ffmpeg', '-re', '-i', f'{video_path}', '-f', 'mpegts', '-c:v', 'copy', '-c:a', 'aac', '-vbsf', 'h264_mp4toannexb', 'pipe:1', # 移除多余的.ts后缀,直接输出到标准输出 ] pa = subprocess.Popen( command, stdout=subprocess.PIPE, stderr=error_file ) # 以追加二进制模式打开管道,将FFmpeg输出分块写入 with pa.stdout, open(pipe_name, 'ab') as pipe_file: # 按4KB块读取输出,避免内存占用过高 for chunk in iter(lambda: pa.stdout.read(4096), b''): pipe_file.write(chunk) pa.wait()
- 调整FFmpeg的输出目标为
pipe:1,这是标准输出的管道标识,.ts后缀是多余的。 - 使用
ab模式打开管道,实现和Shell中>>相同的追加写入效果。
方案2:启用Shell解析重定向(不推荐)
如果一定要保留cat >> pipe的逻辑,可以让subprocess调用Shell来解析重定向语法:
command = [ 'docker', 'run', '-v', f'{cwd}:{cwd}', '-w', f'{cwd}', 'jrottenberg/ffmpeg', '-re', '-i', f'{video_path}', '-f', 'mpegts', '-c:v', 'copy', '-c:a', 'aac', '-vbsf', 'h264_mp4toannexb', 'pipe:1', ] pa = subprocess.Popen( command, stdout=subprocess.PIPE, stderr=error_file ) # 启用shell=True,让Shell处理>>重定向 with pa.stdout: pb = subprocess.Popen( f'cat >> {pipe_name}', stdin=pa.stdout, stdout=error_file, stderr=error_file, shell=True ) pb.wait() pa.wait()
- 注意:
shell=True存在安全风险,如果pipe_name包含不可信输入,可能会触发命令注入漏洞,因此优先推荐方案1。
内容的提问来源于stack exchange,提问作者Eric Palmer
相关产品推荐
相关产品推荐

