在 Python 的 OpenCV 中,并不会直接暴露 FFmpeg 的所有 API 供你调用,因为 OpenCV 只是封装并复用 FFmpeg 的核心能力(而非让你直接操作 FFmpeg)。不过你可以通过两种思路实现"调用 FFmpeg 特定功能"的需求:
思路 1:通过 OpenCV 接口间接使用 FFmpeg 能力(最常用)
OpenCV 封装了 FFmpeg 最核心的视频处理功能(如指定编码、设置帧率/分辨率、读取特殊格式),你可以通过 OpenCV 的 API 来控制这些 FFmpeg 底层行为,以下是最实用的场景示例:
场景 1:指定视频编码格式(调用 FFmpeg 的编码功能)
当你用 cv2.VideoWriter 保存视频时,可指定 FFmpeg 支持的编码(如 H.264、H.265),本质是调用 FFmpeg 的编码库:
python
import cv2
import numpy as np
# 1. 读取视频(底层由 FFmpeg 解析)
cap = cv2.VideoCapture("input.mp4")
if not cap.isOpened():
raise Exception("无法打开视频文件(FFmpeg 解析失败)")
# 获取原视频参数
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# 2. 指定 FFmpeg 编码格式保存视频
# 关键:设置 FourCC 编码(对应 FFmpeg 的编码标识)
# H.264 编码(最通用):FourCC 为 'mp4v'/'avc1',MP4 容器
fourcc = cv2.VideoWriter_fourcc(*'avc1') # avc1 是 FFmpeg 的 H.264 编码标识
# H.265 编码:fourcc = cv2.VideoWriter_fourcc(*'hev1')(需 FFmpeg 支持)
# 创建 VideoWriter(底层调用 FFmpeg 写入视频)
out = cv2.VideoWriter(
"output_h264.mp4", # 输出文件
fourcc, # 编码格式(FFmpeg 驱动)
fps, # 帧率
(width, height) # 分辨率
)
# 3. 逐帧处理并保存
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
out.write(frame) # 底层由 FFmpeg 编码并写入
# 释放资源
cap.release()
out.release()
cv2.destroyAllWindows()
场景 2:设置 FFmpeg 读取参数(如超时、缓存)
OpenCV 的 VideoCapture 支持通过 CAP_PROP_FFMPEG_OPTS 传递 FFmpeg 原生参数,实现更精细的控制:
python
import cv2
# 调用 FFmpeg 的参数:设置网络流超时(如读取 RTSP 视频)
ffmpeg_opts = {
"rtsp_transport": "tcp", # 强制 TCP 传输(FFmpeg 原生参数)
"stimeout": "5000000" # 超时 5 秒(单位:微秒,FFmpeg 参数)
}
# 将参数转为 OpenCV 可识别的字符串格式
opts_str = ";".join([f"{k}={v}" for k, v in ffmpeg_opts.items()])
# 打开 RTSP 流(底层由 FFmpeg 处理,应用自定义参数)
cap = cv2.VideoCapture("rtsp://example.com/stream")
cap.set(cv2.CAP_PROP_FFMPEG_OPTS, opts_str)
if cap.isOpened():
ret, frame = cap.read()
if ret:
cv2.imwrite("rtsp_frame.jpg", frame)
cap.release()
场景 3:读取 FFmpeg 支持的特殊格式(如网络流、音频视频分离)
python
import cv2
# 读取 FFmpeg 支持的网络视频流(如 YouTube-dl 导出的流、直播流)
# 底层完全依赖 FFmpeg 解析协议和编码
cap = cv2.VideoCapture("http://example.com/live/stream.m3u8")
# 循环读取帧
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
cv2.imshow("FFmpeg Stream", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
思路 2:直接调用 FFmpeg 命令行(实现 OpenCV 封装外的功能)
如果需要 FFmpeg 的高级功能(如音频处理、视频剪辑、格式转换),OpenCV 封装的接口不够用,可通过 Python 的 subprocess 直接调用系统的 FFmpeg 命令行(这是更灵活的方式):
前提:
先安装独立的 FFmpeg(官网下载:https://ffmpeg.org/),确保终端能执行 ffmpeg 命令。
示例:用 FFmpeg 提取视频音频 + OpenCV 处理视频帧
python
import cv2
import subprocess
import os
# 1. 用 FFmpeg 提取视频中的音频(OpenCV 不支持音频处理)
input_video = "input.mp4"
output_audio = "audio.mp3"
ffmpeg_audio_cmd = [
"ffmpeg", "-i", input_video, # 输入视频
"-vn", # 忽略视频流
"-acodec", "mp3", # 音频编码
output_audio
]
# 执行 FFmpeg 命令
subprocess.run(ffmpeg_audio_cmd, check=True, capture_output=True)
# 2. 用 OpenCV 处理视频帧(依赖 FFmpeg 解析视频)
cap = cv2.VideoCapture(input_video)
frame_count = 0
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# 对帧进行处理(如灰度化)
gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 保存处理后的帧
cv2.imwrite(f"frame_{frame_count}.jpg", gray_frame)
frame_count += 1
cap.release()
# 3. 用 FFmpeg 将处理后的帧 + 原音频合成新视频
ffmpeg_merge_cmd = [
"ffmpeg", "-framerate", "30", # 帧率
"-i", "frame_%d.jpg", # 输入帧序列
"-i", output_audio, # 输入音频
"-c:v", "libx264", # 视频编码(FFmpeg 的 H.264)
"-c:a", "aac", # 音频编码
"-pix_fmt", "yuv420p", # 像素格式
"merged_video.mp4" # 输出视频
]
subprocess.run(ffmpeg_merge_cmd, check=True, capture_output=True)
# 清理临时文件
os.remove(output_audio)
for i in range(frame_count):
os.remove(f"frame_{i}.jpg")
关键说明
-
FourCC 编码对应关系 (OpenCV ↔ FFmpeg):
OpenCV FourCC FFmpeg 编码 适用容器 avc1/mp4vlibx264 MP4 hev1/hvc1libx265 MP4 vp09libvpx-vp9 WebM -
FFmpeg 参数传递 :
cv2.CAP_PROP_FFMPEG_OPTS支持大部分 FFmpeg 原生参数(如rtsp_transport、buffer_size、timeout等),参数格式需符合 FFmpeg 要求。 -
兼容性 :如果 OpenCV 未启用 FFmpeg,上述
VideoCapture/VideoWriter会失效,需重新安装带 FFmpeg 的 OpenCV(pip install opencv-python)。
总结
- 基础视频处理 :直接用 OpenCV 的
VideoCapture/VideoWriter,底层自动调用 FFmpeg,通过 FourCC、CAP_PROP_FFMPEG_OPTS控制 FFmpeg 行为; - 高级 FFmpeg 功能 :用 Python
subprocess调用 FFmpeg 命令行,结合 OpenCV 处理视频帧,实现音频/视频分离、格式转换等; - 核心逻辑:OpenCV 封装了 FFmpeg 的视频编解码能力,复杂需求需直接调用 FFmpeg 命令行。