获取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
相关产品推荐
相关产品推荐

