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

使用Python FFmpeg子进程读取RTMP源时帧垂直滚动问题求助

解决FFmpeg+OpenCV处理RTMP流时画面垂直滚动的问题

这种画面垂直滚动/上下颠倒的问题我碰到过好多次,本质都是FFmpeg输出的原始帧数据和OpenCV的存储行顺序不匹配导致的——FFmpeg默认输出的rawvideo很多时候是采用「从底部行开始存储」的bottom-up格式,而OpenCV则是「从顶部行开始存储」的top-down格式,两者一结合,画面自然就会出现滚动或者上下翻转的情况。下面给你两种直接可行的解决方案,附完整代码:

方案一:让FFmpeg输出匹配OpenCV的格式(推荐)

直接在FFmpeg命令中指定输出为OpenCV原生支持的bgr24像素格式,同时确保帧的行顺序和OpenCV对齐。这样可以避免后续额外的翻转操作,效率更高。

完整代码示例(含显示+推流)

import subprocess
import numpy as np
import cv2

# ---------------------- 1. 配置FFmpeg读取RTMP流 ----------------------
# 获取流的宽高(用FFprobe自动获取,避免硬编码)
ffprobe_cmd = [
    'ffprobe',
    '-v', 'error',
    '-select_streams', 'v:0',
    '-show_entries', 'stream=width,height',
    '-of', 'csv=p=0',
    'rtmp://your-input-stream-url'  # 替换成你的输入RTMP地址
]
stream_info = subprocess.check_output(ffprobe_cmd).decode('utf-8').strip()
width, height = map(int, stream_info.split(','))

# FFmpeg命令:读取RTMP流,输出BGR24格式的rawvideo到管道
ffmpeg_read_cmd = [
    'ffmpeg',
    '-i', 'rtmp://your-input-stream-url',
    '-f', 'rawvideo',
    '-pix_fmt', 'bgr24',  # 匹配OpenCV的BGR格式
    '-vcodec', 'rawvideo',
    '-an',  # 忽略音频
    '-sn',  # 忽略字幕
    '-r', '30',  # 帧率和输入流保持一致
    '-y',
    'pipe:1'
]
read_process = subprocess.Popen(ffmpeg_read_cmd, stdout=subprocess.PIPE, bufsize=10**8)

# ---------------------- 2. 配置FFmpeg推流到RTMP(可选) ----------------------
ffmpeg_push_cmd = [
    'ffmpeg',
    '-f', 'rawvideo',
    '-pix_fmt', 'bgr24',
    '-s', f'{width}x{height}',
    '-r', '30',
    '-i', 'pipe:0',
    '-c:v', 'libx264',
    '-preset', 'ultrafast',  # 推流优先保证实时性
    '-f', 'flv',
    'rtmp://your-output-stream-url'  # 替换成你的输出RTMP地址
]
push_process = subprocess.Popen(ffmpeg_push_cmd, stdin=subprocess.PIPE)

# ---------------------- 3. 帧处理循环 ----------------------
while True:
    # 读取一帧的原始数据:BGR24格式每个像素占3字节,所以总字节数是width*height*3
    raw_frame = read_process.stdout.read(width * height * 3)
    if not raw_frame:
        break  # 流结束
    
    # 转换为OpenCV可用的numpy数组
    frame = np.frombuffer(raw_frame, dtype=np.uint8).reshape((height, width, 3))
    
    # ---------------------- 4. 你的业务处理逻辑 ----------------------
    # 示例:画一个绿色矩形
    cv2.rectangle(frame, (50, 50), (200, 200), (0, 255, 0), 2)
    
    # ---------------------- 5. 显示或推流 ----------------------
    # 显示画面
    cv2.imshow('Processed Stream', frame)
    
    # 推流处理后的帧
    push_process.stdin.write(frame.tobytes())
    
    # 按Q键退出循环
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# ---------------------- 清理资源 ----------------------
read_process.terminate()
push_process.terminate()
cv2.destroyAllWindows()

方案二:在OpenCV中垂直翻转帧(兜底方案)

如果因为某些原因无法修改FFmpeg的输出格式,那可以在拿到OpenCV帧后,直接用cv2.flip()做垂直翻转,解决行顺序不匹配的问题:

# 在转换为numpy数组后添加这一行
frame = cv2.flip(frame, 0)  # 参数0表示垂直翻转(上下颠倒)

常见排查要点

  1. 确认像素格式匹配:FFmpeg输出的像素格式要和OpenCV处理的格式对应(比如OpenCV默认用BGR,不要输出RGB)
  2. 检查字节数读取正确:确保每次读取的字节数是width * height * 每个像素的字节数(BGR24是3,YUV420p是1.5)
  3. 帧率同步:推流时指定的帧率要和输入流一致,否则也可能出现画面卡顿或滚动

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:00:42