[FFmpeg] 如何通过实时摄像头帧图片生成 rtmp 直播流? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
ZoomQuiet
V2EX    程序员

[FFmpeg] 如何通过实时摄像头帧图片生成 rtmp 直播流?

  •  
  •   ZoomQuiet
    ZoomQuiet 2018-03-08 20:23:29 +08:00 18730 次点击
    这是一个创建于 2778 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景

    • 已经完成用 Python 对摄像头硬件实时提取帧图像并进行一系列机械视觉处理
    • 客户突然提出, 一定要通过 rtml:// 进行远程工作状态的监控

    分析

    • 因为硬件驱动的原因
    • 系统中一个 usb camera, 同一时刻, 只能有一个加载进程来读取实时帧图像
    • 如果如客户自己实验通过的:
      • FFmpeg -f dshow -i video="... -f mpegts -f flv "rtmp://20878.... 形式
      • 从硬件直接拿视频并实时编译为 flv 编码的 rtmp 直播流
      • 那么, 原先软件将无法获得合法的帧图像进行业务分析

    尝试

    • 知道 FFmpeg 有能力从图片中编译出 avi/mp4/... 视频
    • 那么一定也可以编译为 rtmp 直播流

    问题

    动态固定图片

    尝试将实时帧图像,另外输出到硬盘固定图片文件, 内容动态变化,

    命令改变为: ffmpeg -f image2 -loop 1 -i "path/2/frame.png" ...

    但是, 无论怎么调整参数,都只能工作十多帧就崩溃了, 报错都是类似:

    ... Error while decoding stream #0:0: Invalid data found when processing input Last message repeated 1 times Past duration 0.799995 too large [flv @ 0x7fabfa001800] Failed to update header with correct duration.34.3kbits/s dup=0 drop=1120 speed=7.25x [flv @ 0x7fabfa001800] Failed to update header with correct filesize. frame= 1730 fps=109 q=5.5 Lsize= 3300kB time=00:01:55.40 bitrate= 234.3kbits/s dup=0 drop=1120 speed=7.24x video:3273kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.832250% 

    系列静态图片

    而将帧图像持续输出为一系列有命名规模的静态图片后, 参考:

    无论怎么折腾参数, 都无法工作, 报错为:

    ... Metadata: encoder : Lavf57.71.100 Stream #0:0: Video: flv1 (flv) ([2][0][0][0] / 0x0002), yuv420p, 480x270, q=2-31, 200 kb/s, 25 fps, 1k tbn, 25 tbc Metadata: encoder : Lavc57.89.100 flv Side data: cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: -1 [flv @ 0x7ff53d008600] Failed to update header with correct duration. [flv @ 0x7ff53d008600] Failed to update header with correct filesize. frame= 20 fps=0.0 q=9.7 Lsize= 173kB time=00:00:00.76 bitrate=1867.3kbits/s speed=10.1x video:173kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.300397% 

    所以, 综合以上, 想知道如何能通过动态图片 /实时增长的系列图片 实时编译为 rmtp 直播流?

    或是说, 思路上还有什么选择?

    第 1 条附言    2018-03-14 00:01:07 +08:00

    解决+回顾

    问题其实应该是:

    如何通过[FFmpeg]将 webcam 实时帧数据合法推送给第3方 rtmp 直播频道?

    @Panic 一语中的:

    应该就是使用 pipe,先将 png 转成 rgb 格式或 YUV 格式的 rawvideo, 再送到 ffmpeg 的 pipe 进行编码,输出 rtmp 到...

    回顾之前收集到的有关文章:

    重新构建了测试脚本实现了实时推送, 延时也在容忍范畴之内 ;-)

    注意:

    命令参数一定要有:

    , '-f', 'rawvideo' , '-vcodec','rawvideo' 

    对应的, 要将 cv2 处理的图片格式, 从 numpy.ndarray->cv2.cv.cvmat

    才能使用 .tostring() 通过 stdin 丢给 FFmpeg 完成格式化并推送

    回顾:

    大家的各种质疑, 主要还是系统架构的决策问题:

    • 为毛不用 FFmpeg 直接从硬件获得图像并推流?
    • 简单的说, 这是业务决定的...
    • 之前尝试过, 但是, 透过 FFmpeg 的自动化视频流处理后
      • 应用系统再难获得合理/时间线同步的帧数据了
      • 因为系统包含了一组多个摄像头
      • 而业务是严重依赖所有视觉数据的帧时间戳信息
    • 进一步的, 尝试先将硬件实时图像先吐到本地 UDP 通道中
      • 然后无论机械视觉业务
      • 视频记录功能
      • rmtp 之类远程监察要求
      • ...
      • 都可以另外用单独进程从 UDP 并行提取
      • 但是, 依然失败了...
    • 所以, 才恢复了用 Python 直读硬件信息并处理
      • 实时输出硬盘帧图片
      • 后期再用 FFmpeg 生成各种期待的格式视频
    • 只是年后, 突然有了 rmtp 通道...这才想在原有架构上追加个输出渠道
    • 万幸的是 win10 系统也有 stdin 的机制,否则, 当前这方案也得瞎...

    PS:

    同时在尝试其它渠道来提问, 但是 V2Ex 的响应最快, 最多...

    实在是...

    C'est la vie (-ι_-`) 
    34 条回复    2019-03-26 11:31:12 +08:00
    contmonad
        1
    contmonad  
       2018-03-08 21:47:33 +08:00
    经过磁盘文件中转后实时性不好吧,直接用 pipe。这里有个 OpenCV 到 FFmpeg 的例子: https://stackoverflow.com/q/36422211/3107204

    我猜用 FFmpeg 的 Python binding 也可以( libavdevice 操作摄像头,libavformat 转封装),而且自由度更高。
    contmonad
        2
    contmonad  
       2018-03-08 21:51:17 +08:00
    你帖子中的描述概念错误好多啊。。建议找 H.264 和 RTMP 的规范看一下
    wdlth
        3
    wdlth  
       2018-03-08 22:11:37 +08:00 via Android
    为何不直接传输视频流?
    likuku
        4
    likuku  
       2018-03-08 22:55:11 +08:00
    rtmp 传输的也就是包装成 flv 的 h264 流 (video: h264, audio: aac)
    likuku
        5
    likuku  
       2018-03-08 22:56:38 +08:00
    ffmpeg 本身就具有直接读取摄像头抓取信息的能力,只要你机器编码足够快(GPU 之类加速就 OK),实时推流不是问题
    fgodt
        6
    fgodt  
       2018-03-08 22:59:21 +08:00 via Android
    不是很懂你的构架,正常的如果有图片源用 ffmpeg 编成 264 封装成 flv 输出到 rtmp 地址就行了
    picone
        7
    picone  
       2018-03-09 01:13:28 +08:00
    动态图片不可行,刚好我毕设在做相关的项目,可以一起讨论。
    因为是本科生的毕设,所以就用动态图片实现了,websocket+protobuf,传输图片,前端 img 加载。
    后端用 APS 定时抓帧,用 jpeg 编码再推送出去。
    我的 mac 跑,9fps,单核 cpu 跑满。。。再高的 fps 就有延迟了。。。
    https://github.com/picone/RealTimeTrackingCamera
    你可以用 jsmpeg 实现以下,把视频用 mpeg 压缩,效果会好很多
    ETiV
        8
    ETiV  
       2018-03-09 02:26:39 +08:00
    // 可能需要重写 Python 的部分

    摄像头 -> FFmpeg -> nginx-rtmp -> 通过指令 push 把直播流推出去 -> 直播站点
                 \-> Python (或 FFmpeg )读 rtmp:// 直播流,拆出来图片 -> Python 分析
    ZoomQuiet
        9
    ZoomQuiet  
    OP
       2018-03-09 07:15:09 +08:00 via iPhone
    @likuku 是也乎 ()

    多谢提醒…可以无声的…推流~
    ZoomQuiet
        10
    ZoomQuiet  
    OP
       2018-03-09 07:18:02 +08:00 via iPhone
    @ETiV 试过…不可用…
    机械视觉部分实时要求高…

    且需要用原帧~
    从第三方直播服装绕时间轴全乱套了…

    是也乎 ()
    ZoomQuiet
        11
    ZoomQuiet  
    OP
       2018-03-09 07:19:04 +08:00 via iPhone
    @fgodt 是也乎 ()

    正常的是图片已准备好…
    俺这是实时动态生成的…
    ZoomQuiet
        12
    ZoomQuiet  
    OP
       2018-03-09 07:20:37 +08:00 via iPhone
    @contmonad
    是也乎 ()

    多谢提醒…概念术语的确不准…
    直播方面是二把刀…
    临时突然要追加的…
    ZoomQuiet
        13
    ZoomQuiet  
    OP
       2018-03-09 07:21:26 +08:00 via iPhone
    @contmonad 多谢~
    有方向好探查…

    是也乎 ()
    ZoomQuiet
        14
    ZoomQuiet  
    OP
       2018-03-09 07:23:25 +08:00 via iPhone
    @picone 多谢提醒…
    也尝试过 jsmpeg …官网效果看着好~
    竟然安装不上…
    俺这就再刷一下…
    ZoomQuiet
        15
    ZoomQuiet  
    OP
       2018-03-09 07:57:25 +08:00
    @contmonad 再次感谢
    pipe 是个靠谱的方向, 之前实现过, 都忘记了...

    > ... libavdevice 操作摄像头,libavformat 转封装...

    涉及 FFmpeg 底层 C 库了,这种调试起来就嗯哼了...
    gggxxxx
        16
    gggxxxx  
       2018-03-09 09:01:18 +08:00
    几年前我自己用 librtmp 做过类似的,摄像头画面直接推到 rtmp 服务器。
    不用 ffmpeg 也能实现。
    fgodt
        17
    fgodt  
       2018-03-09 09:34:05 +08:00
    你想不写代码用几个命令来处理还是有点难度,正确的流程应该是
    1 视频流->ffmpeg->pkt
    2 pkt->ffmpeg->图片->py 处理
    3 pkt->ffmpeg->rtmp
    第二步第三步可以互不影响
    Panic
        18
    Panic  
       2018-03-09 10:07:19 +08:00
    应该就是使用 pipe,先将 png 转成 rgb 格式或 YUV 格式的 rawvideo, 再送到 ffmpeg 的 pipe 进行编码,输出 rtmp 到添加了 rtmp 模块的 nginx 服务器。客户端连接通过 rtmp 链接访问 nginx 就可以了。
    retamia
        19
    retamia  
       2018-03-09 10:44:19 +08:00
    你是要将摄像头采集到的图片帧处理后,进行直播推流吗?
    ZoomQuiet
        20
    ZoomQuiet  
    OP
       2018-03-09 18:49:56 +08:00 via iPhone
    @retamia 是也乎 ()

    对的…整体数据流必须这样…

    通过硬盘文件来隔离不同业务…

    否则有硬件争用现象…
    ZoomQuiet
        21
    ZoomQuiet  
    OP
       2018-03-09 18:50:51 +08:00 via iPhone
    @fgodt 是也乎 ()

    pkt 是指数值封装嘛?
    ZoomQuiet
        22
    ZoomQuiet  
    OP
       2018-03-09 18:53:41 +08:00 via iPhone
    @gggxxxx 是也乎 ()

    已在看此模块

    官方样例是从 rmtp 流拿帧的…
    但文档中说能写…

    但只接受 flv 封装的图片…
    然有…找不到可用的… flv 封装模块

    所以…你之前是乍写入上游直播流的?
    nanhuo
        23
    nanhuo  
       2018-03-17 16:12:49 +08:00
    @ZooQuiet 方便透露一下使用这个方案延时最终能控制在什么范围吗?
    ZoomQuiet
        24
    ZoomQuiet  
    OP
       2018-03-17 17:35:48 +08:00 via iPhone
    @nanhuo 是也乎 ()

    国内 3 秒内

    海外 30 秒内

    关键是上游 直播服务平台的资源分布了…
    fqxyhdsy
        25
    fqxyhdsy  
       2018-03-19 14:47:50 +08:00
    @ZoomQuiet 您好,楼主!请问你这问题解决了吗!现在因为业务需求也要弄个类似的!这边现在的情况是,直播流通过 ffmpeg 切帧,将切完的帧存放在了服务器某个文件夹下,然后不停的覆盖该文件。应该就是您上面说的动态固定图片那种情况。请问具体如何结合 pipe,将这个动态固定图片推成一个视频流!刚接触 python 没多久,请详细讲解一哈!谢谢!
    fqxyhdsy
        26
    fqxyhdsy  
       2018-03-20 15:05:04 +08:00
    @picone 您好!请问,动态图片+websocket+protobuf,这种方案怎么用 protobuf 来传输图片呀? 这边之前的解决方案是 socket 传输 base64 数据,前端用 websocket 接受数据然后绑定图片到视图层。但是太吃内存了,服务器承受不了!求解惑!万分感谢!
    picone
        27
    picone  
       2018-03-20 15:49:04 +08:00
    @fqxyhdsy #26 不要转 base64 了,直接把图片 jpeg 编码,然后直接使用 protobuf 序列化就 OK 了,protobuf 接受二进制。如果是连续动态的图片,建议用 mpeg 编码
    fqxyhdsy
        28
    fqxyhdsy  
       2018-03-20 16:04:07 +08:00
    @picone 首先万分感谢回复! 如果将 jpeg(mpeg)编码后的图片用 protobuf 序列化传过去,应该是没问题。但是现在前端是用 js 的 websocket 来链接的!那怎么来反序列化 protobuf 传过来的数据呢! js 这边是否能够支持 protobuf 和 jpeg(mpeg)解码!刚接触没多久,万分包涵!
    picone
        29
    picone  
       2018-03-20 16:09:16 +08:00
    @fqxyhdsy #28 js 也提供了 protobuf,也可以做到。jsmpeg 网上也有项目
    ZoomQuiet
        30
    ZoomQuiet  
    OP
       2018-03-29 19:29:04 +08:00 via iPhone
    @fqxyhdsy 是也乎 ()

    不好意思才看到…

    已有流的话…

    FFmpeg 本身就支持:
    - 拖流为视频文件
    - 或直接转播推流到其它协议流

    进一步的…图片序列少 TPS 信息…体积也大…
    不如存为 .mkv 需要时 --> 推为流
    liu826250634
        31
    liu826250634  
       2018-08-21 19:27:14 +08:00
    题主您好。
    我也是遇到这样的问题,需要从海康摄像头抓取之后进行人脸识别,对视频进行处理之后进行 rtmp 进行推流。
    我的代码:
    size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
    sizeStr = str(size[0]) + 'x' + str(size[1])
    fps = cap.get(cv2.CAP_PROP_FPS) # 30p/self
    fps = int(fps)
    rtmpUrl = 'rtmp://192.168.1.71:1935/live/app'
    command = ['ffmpeg',
    '-y',
    '-f', 'rawvideo',
    '-vcodec','rawvideo',
    '-pix_fmt', 'bgr24',
    '-s', sizeStr,
    '-r', str(fps),
    '-i', '-',
    '-c:v', 'libx264',
    '-pix_fmt', 'yuv420p',
    '-preset', 'ultrafast',
    '-f', 'flv',
    rtmpUrl]

    while True:
    ret, frame = cap.read()
    proc = sp.Popen(command, stdin=sp.PIPE, shell=False)
    proc.stdin.write(frame.tostring())
    if cv2.waitKey(1) & 0xFF == ord('q'):
    break

    运行是成功了(也不能说成功,有时候会崩溃),但是用 VLC 却是不能拉流观看。
    然后再想是否是你说的这个问题,从 numpy.ndarray->cv2.cv.cvmat。
    但是在网上查资料说 mat_array = cv2.cv.fromarray(frame),这个 opencv-python 2.4 之后就没了。
    希望题主看到之后能解答一下!
    ZoomQuiet
        32
    ZoomQuiet  
    OP
       2018-12-01 17:46:42 +08:00
    [FFmpeg] Python 2.7 怎样合理的包裹外部指令安定调用第三方工具并安全结束? - V2EX
    t/513363#reply0

    新问题....
    ZoomQuiet
        33
    ZoomQuiet  
    OP
       2018-12-01 17:49:41 +08:00
    @liu826250634 是也乎,( ̄ ̄)
    这也是为什么, 我们一直没升级到 Py3+cv3 的原因,
    py2.7.X+OpenCV2.4.X 的组合足够安定就没理由升级到可能更好的体系...

    另外, VLC 版本也有不同的问题.
    建议参考 FFmpeg 官方文档, 先用 ffplayer 来检验 rmtp 是否真正推流成功...

    以及, 俺的经验, 这个 rmtp 最好还是先走 腾讯云的视频流服务,
    完成一个安定的数据流....
    否则, 本地局网的情况太复杂....不好判定
    hellotiny
        34
    hellotiny  
       2019-03-26 11:31:12 +08:00
    博主你好啊,我也遇到这个问题,不太理解基于 pipe 进行数据共享推流的这个原理,想问逻辑问题。
    通过管道的方式实现的哪一种形式呢?
    一是将处理过的图片缓存进 buff 中形成了有顺序的帧形成的视频流,使用 ffmpeg 推出的就是 buff 中缓存的视频流吗?
    那么推流时抓图和处理图片的进程会不会暂停?
    二是处理一帧放入管道,然后就通过 ffmpeg 推送一帧到 rtmp 服务器吗?
    我没办法判断我通过 pipe 推流有没有成功,我在 RTMP 播放器中输入推流的 RTMP 地址是没有直播在播放的。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5357 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 41ms UTC 01:20 PVG 09:20 LAX 18:20 JFK 21:20
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86