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

获取FFmpeg执行结果并传入Python脚本的实现方案咨询

解决方案:捕获FFmpeg输出并自动上传分段视频

我来帮你一步步实现这个需求——既可以捕获FFmpeg的执行日志/结果,又能自动把完成的视频片段上传到指定位置,完全适配你的树莓派场景。

1. 捕获FFmpeg的执行输出到Python

要把FFmpeg的运行结果(包括日志、错误信息、返回码)传入Python,最靠谱的方式是用Python的subprocess模块直接调用FFmpeg命令,同时捕获它的标准输出和错误输出。这样你可以实时处理日志,或者在命令结束后分析结果。

示例代码:捕获FFmpeg输出

import subprocess
import time

def run_ffmpeg_and_capture_output():
    ffmpeg_cmd = [
        "ffmpeg",
        "-i", "http://0.0.0.0:8080/stream/video.mjpeg",
        "-vcodec", "copy",
        "-map", "0",
        "-f", "segment",
        "-segment_time", "5",
        "-segment_format", "mp4",
        "capture-%05d.mp4"
    ]
    
    # 启动FFmpeg子进程,捕获stdout和stderr
    process = subprocess.Popen(
        ffmpeg_cmd,
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,  # 把stderr合并到stdout,方便统一处理
        text=True  # 以文本模式读取输出,不用处理字节
    )
    
    # 实时读取FFmpeg的输出
    while True:
        line = process.stdout.readline()
        if not line and process.poll() is not None:
            break
        if line:
            # 这里可以根据你的需求处理输出,比如打印、写入日志文件、触发告警等
            print(f"FFmpeg输出: {line.strip()}")
            # 示例:如果输出包含"segment:",说明生成了新的视频片段,可以触发上传
            if "segment:" in line:
                # 提取文件名,比如从"segment: writing capture-00001.mp4"中获取
                filename = line.split("writing")[-1].strip()
                print(f"新片段生成:{filename},准备上传")
                # 调用上传函数(后面会实现)
                upload_video(filename)
    
    # 获取FFmpeg的返回码
    return_code = process.returncode
    print(f"FFmpeg进程结束,返回码: {return_code}")
    return return_code

这里的关键是用subprocess.Popen启动FFmpeg,同时捕获输出。另外,FFmpeg的日志里会包含segment: writing capture-xxxxxx.mp4这样的行,刚好可以用来触发新片段的上传,避免上传正在写入的文件。

2. 实现视频片段上传功能

接下来是上传逻辑,你需要根据你的"指定位置"来调整代码——比如是本地网络共享文件夹、FTP服务器、云存储等。下面给出几个常见场景的示例:

场景1:上传到本地网络共享文件夹(SMB)

如果是Windows共享或者NAS的SMB目录,可以用pysmb库:

from smb.SMBConnection import SMBConnection

def upload_video_to_smb(filename, smb_config):
    # smb_config是一个字典,包含服务器地址、共享名、用户名、密码等
    conn = SMBConnection(
        smb_config["username"],
        smb_config["password"],
        "raspberrypi",  # 本地机器名,随便填
        smb_config["server_name"],
        use_ntlm_v2=True
    )
    conn.connect(smb_config["server_ip"], 139)
    
    with open(filename, "rb") as f:
        conn.storeFile(smb_config["share_name"], f"uploads/{filename}", f)
    
    conn.close()
    print(f"已上传 {filename} 到SMB共享")

场景2:上传到FTP服务器

用ftplib库:

import ftplib

def upload_video_to_ftp(filename, ftp_config):
    ftp = ftplib.FTP(ftp_config["server_ip"])
    ftp.login(ftp_config["username"], ftp_config["password"])
    ftp.cwd(ftp_config["remote_dir"])
    
    with open(filename, "rb") as f:
        ftp.storbinary(f"STOR {filename}", f)
    
    ftp.quit()
    print(f"已上传 {filename} 到FTP服务器")

通用上传模板(替换成你的逻辑)

如果是其他存储服务,只需要替换这个函数的内容:

def upload_video(filename):
    # 这里写你的上传逻辑,比如复制到本地目录、调用云SDK等
    # 示例:复制到本地另一个目录
    import shutil
    target_dir = "/path/to/your/upload/dir"
    shutil.copy(filename, target_dir)
    print(f"已上传 {filename} 到 {target_dir}")

3. 整合完整脚本,适配树莓派

把上面的部分整合起来,还要考虑树莓派的资源限制——比如不要让上传占用太多CPU/带宽,影响FFmpeg的推流保存。可以用线程来异步处理上传,避免阻塞FFmpeg的输出捕获:

import subprocess
import shutil
import threading

def upload_video(filename):
    # 替换成你的实际上传逻辑
    target_dir = "/mnt/nas/video_uploads"
    try:
        shutil.copy(filename, target_dir)
        print(f"✅ 成功上传: {filename}")
    except Exception as e:
        print(f"❌ 上传失败 {filename}: {str(e)}")

def run_ffmpeg_and_monitor():
    ffmpeg_cmd = [
        "ffmpeg",
        "-i", "http://0.0.0.0:8080/stream/video.mjpeg",
        "-vcodec", "copy",
        "-map", "0",
        "-f", "segment",
        "-segment_time", "5",
        "-segment_format", "mp4",
        "-loglevel", "info",  # 控制FFmpeg的日志级别,避免太冗余
        "capture-%05d.mp4"
    ]
    
    process = subprocess.Popen(
        ffmpeg_cmd,
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        text=True
    )
    
    for line in iter(process.stdout.readline, ''):
        line = line.strip()
        if not line:
            continue
        print(f"[FFmpeg] {line}")
        # 检测新片段生成的日志
        if "segment: writing" in line:
            filename = line.split("writing")[-1].strip()
            # 用线程异步上传,不阻塞FFmpeg的日志处理
            upload_thread = threading.Thread(target=upload_video, args=(filename,))
            upload_thread.start()
    
    return_code = process.wait()
    print(f"FFmpeg进程退出,返回码: {return_code}")

if __name__ == "__main__":
    print("启动FFmpeg推流保存与上传服务...")
    run_ffmpeg_and_monitor()

额外优化建议

  • 避免重复上传:可以维护一个已上传文件的列表(比如存在本地txt文件里),每次上传前检查是否已经上传过。
  • 文件清理:上传完成后,可以删除本地的视频片段,节省树莓派的存储空间。
  • 日志持久化:把FFmpeg的输出和上传日志写入本地文件,方便后续排查问题。
  • 异常处理:给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:06:37