You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python脚本中执行含FFmpeg的复杂Shell命令?

在Python中执行带管道的FFmpeg命令并捕获输出

我来帮你搞定这个问题——要在Python里执行这条包含FFmpeg、grep和gawk的管道命令,并且实时捕获生成的分段文件名,其实有两种靠谱的实现方式,我给你详细说说:

方案一:直接用shell解析整个命令

如果你的命令是固定的,不用担心shell注入风险,直接把整个命令字符串传给subprocess并启用shell=True是最省事的方式:

import subprocess

# 把你的完整命令直接写在这里
full_cmd = '''ffmpeg -i http://0.0.0.0:8080/stream/video.mjpeg -vcodec copy -map 0 -f segment -segment_time 2 -loglevel 40 -segment_format mp4 capture-%05d.mp4 2>&1 | grep --line-buffered -Eo "segment:.+ended" | gawk -F "'" '{print $2; system("")}' '''

# 启动进程,同时捕获stdout和stderr(因为FFmpeg日志输出到stderr)
proc = subprocess.Popen(
    full_cmd,
    shell=True,
    stdout=subprocess.PIPE,
    stderr=subprocess.STDOUT,
    text=True  # 让输出以字符串形式返回,不用手动解码
)

# 实时逐行读取输出
for line in iter(proc.stdout.readline, ''):
    cleaned_line = line.strip()
    if cleaned_line:
        print(f"刚生成的分段文件:{cleaned_line}")
        # 这里可以加你自己的逻辑,比如把文件名存到列表、触发后续处理等

# 等待进程结束,获取返回码
proc.wait()

为什么这么写?

  • shell=True让系统shell帮你处理管道逻辑,不用自己拼接多个进程
  • stderr=subprocess.STDOUT把FFmpeg的错误输出(也就是它的日志)重定向到stdout,这样我们只需要读一个流就行
  • iter(proc.stdout.readline, '')用来实时读取输出,避免进程阻塞,确保每生成一个文件就能立刻拿到文件名

方案二:手动拼接管道(更安全)

如果担心shell注入风险,或者想更灵活地控制每个命令,可以把每个工具拆成独立的subprocess进程,手动连接它们的输入输出:

import subprocess

# 1. 启动FFmpeg进程
ffmpeg_proc = subprocess.Popen(
    [
        'ffmpeg', '-i', 'http://0.0.0.0:8080/stream/video.mjpeg',
        '-vcodec', 'copy', '-map', '0', '-f', 'segment',
        '-segment_time', '2', '-loglevel', '40',
        '-segment_format', 'mp4', 'capture-%05d.mp4'
    ],
    stdout=subprocess.PIPE,
    stderr=subprocess.STDOUT,
    text=True
)

# 2. 启动grep进程,把FFmpeg的输出作为grep的输入
grep_proc = subprocess.Popen(
    ['grep', '--line-buffered', '-Eo', 'segment:.+ended'],
    stdin=ffmpeg_proc.stdout,
    stdout=subprocess.PIPE,
    text=True
)
# 关闭FFmpeg的stdout,这样当grep结束时FFmpeg会收到SIGPIPE信号终止
ffmpeg_proc.stdout.close()

# 3. 启动gawk进程,把grep的输出作为gawk的输入
gawk_proc = subprocess.Popen(
    ['gawk', '-F', "'", '{print $2; system("")}'],
    stdin=grep_proc.stdout,
    stdout=subprocess.PIPE,
    text=True
)
grep_proc.stdout.close()

# 读取gawk的最终输出
for line in iter(gawk_proc.stdout.readline, ''):
    cleaned_line = line.strip()
    if cleaned_line:
        print(f"刚生成的分段文件:{cleaned_line}")

# 等待所有进程结束
gawk_proc.wait()
grep_proc.wait()
ffmpeg_proc.wait()

关键注意点

  • 一定要加--line-buffered参数给grep和gawk,否则它们会用块缓冲模式,导致输出不会实时传递给Python,你要等很久才能拿到结果
  • system("")在gawk里是用来强制刷新输出缓冲的,这个不能省略,否则同样会出现输出延迟的问题
  • 如果你的系统里这些工具的路径不是全局可访问的,可以写绝对路径(比如/usr/bin/ffmpeg)来避免找不到命令的问题

额外提醒

  • 确保你的系统已经安装了ffmpeg、grep和gawk这三个工具
  • 如果需要长时间运行脚本,建议加上异常处理(比如捕获KeyboardInterrupt来优雅终止所有进程)
  • 测试的时候可以先把FFmpeg的输入换成本地视频文件,这样更容易调试

内容的提问来源于stack exchange,提问作者Rex Low

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:26:24