V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
mikulch
V2EX  ›  Java

关于直播视频流处理后再转播的技术架构选型

  •  
  •   mikulch · 2022-03-15 07:48:53 +08:00 · 3920 次点击
    这是一个创建于 1014 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近有一些需求都跟这个有关,以前都没做过这种实时视频流的处理,都是 crud boy 。目前后端语言是一定要选 java 的。 但是对于这一块基本上一片空白。大家有什么推荐的教程或者书籍么?网上自己搜了下,没什么特别满意的比较全面的教程。

    第 1 条附言  ·  2022-03-15 10:21:39 +08:00
    需求是
    1. 将 A 源 ( hls ) 的流逐帧解码后,送到一个 api 处理(逐帧 /图片),处理后重新编码封装成新的视频流。
    2. 将封装好的新的视频流推给流媒体服务器,供他人观看。
    3. 没有并发要求,也就甲方在某几个特定的地址下,看下不同摄像头的视频监控。

    技术选型
    1. 后端 java
    2. 流媒体服务器:ssr

    遇到的问题:
    1. 因为推流端的解码、编码、封装、再推送的动作特别吃 cpu ,基本上一台机器的 cpu 吃掉 80%。
    2. 如果把推流端和拉流端弄到一台服务器,用户直接观看 ssr 分发的视频会速度很慢。
    3. 因为要把每一帧的图片,通过一个 api 处理,处理后推送到 ssr ,这时候造成 ssr 在观看直播时,画面非常容易卡着缓冲,等推流端推送足够多的帧。这方面的性能优化,在 java 应用层的层面还有什么可以做的吗?

    谢谢大家
    44 条回复    2022-03-16 18:52:58 +08:00
    RedBeanIce
        1
    RedBeanIce  
       2022-03-15 08:19:39 +08:00 via iPhone
    好像有什么 rtmp 还有什么鬼技术,不记得,等一个大佬回复
    smilzman
        2
    smilzman  
       2022-03-15 08:29:51 +08:00
    1. 使用云服务,有转码服务
    2. 用 ffmpeg
    3. 搜索 Java 流媒体
    q1angch0u
        3
    q1angch0u  
       2022-03-15 08:40:29 +08:00 via iPhone
    chenbokais3
        4
    chenbokais3  
       2022-03-15 08:41:25 +08:00
    gstreamer rtsp
    des
        5
    des  
       2022-03-15 08:56:07 +08:00 via iPhone
    估计问的是多流合并、水印这种东西,不是纯转码
    我也蹲一个答案
    des
        6
    des  
       2022-03-15 08:57:26 +08:00 via iPhone
    顺便多说一句,这个方面的 Java 是基本不要想了
    andyskaura
        7
    andyskaura  
       2022-03-15 09:19:23 +08:00
    ffmpeg 将直播流切片保存在本地 然后加工后 接着用它推出去 具体工作 ffmpeg 都能干 你衔接好流程就行
    ybnsjl
        8
    ybnsjl  
       2022-03-15 09:49:32 +08:00
    ffmpeg + rtmp + nginx
    Huelse
        9
    Huelse  
       2022-03-15 09:49:58 +08:00
    Ant Media
    Huelse
        10
    Huelse  
       2022-03-15 09:51:50 +08:00
    darkengine
        11
    darkengine  
       2022-03-15 10:01:01 +08:00
    你们直播的音视频流处理都是自己做的吗?我们项目用的商用 SDK ,视频流处理这些都带了
    LLaMA2
        12
    LLaMA2  
       2022-03-15 10:01:52 +08:00   ❤️ 1
    需求不明,无法给到您更好的建议,
    hu8245
        13
    hu8245  
       2022-03-15 10:03:03 +08:00
    搞这个的,分推拉,推的话,国内主要用 rtmp ,( youtuebe twitch 也是),你可能需要在服务器段进行转封装或转码,这个想简单的话就 ffmpeg 了,或者有音视频开发资源的话,自己去开发,成本比较大。拉流就随意了,DASH/HLS 都支持 low latency ,还是有现成的方案的。主要还是在服务器这里,没有 C/C++ 技术栈去深入的话,基本上就只能用现成的。
    mikulch
        14
    mikulch  
    OP
       2022-03-15 10:10:10 +08:00
    @smilzman

    @andyskaura
    @darkengine
    @hu8245
    感谢各位大佬,我这边的需求其实是这样。
    有一个直播的 hls 格式来源,是个视频流的地址。这个地址可以通过 java 封装的 ffmpeg 抓取到帧,然后需求需要把每一帧的图片,通过另外一个图片 APi 做一下处理,然后重新转码封装成 rtmp 格式的视频流推到流媒体服务器。

    现在流媒体服务器用的国产的 ssr 。遇到的问题,是拉流端 即 -> 抓取直播 hls 数据,解码成图片,然后 api 处理后重新编码封装成视频格式这里,非常的耗费 cpu 资源。

    一台服务器起码吃掉 80%,不知道是否有可能可以解决?
    mikulch
        15
    mikulch  
    OP
       2022-03-15 10:22:07 +08:00
    @ye4tar
    @ybnsjl
    @des
    @q1angch0u

    谢谢各位大佬,详细内容已经补充到了问题中。
    locoz
        16
    locoz  
       2022-03-15 10:24:41 +08:00 via Android
    @mikulch #14 每一帧的图片调一次 API 做一次处理再重新拼成视频…这么处理吃 CPU 是必然的。建议描述一下这个图片 API 做了什么事,看看有没有什么更合适的解决办法。
    microxiaoxiao
        17
    microxiaoxiao  
       2022-03-15 10:26:09 +08:00 via Android
    编解码不吃 CPU 就吃 GPU 你这个方案可以有两个可能改善的效果。解码成 raw 数据,然后 api 处理 raw 数据,再编码,可以少编码解码过程。其次就是用硬件 GPU ,降低 CPU 使用。
    andyskaura
        18
    andyskaura  
       2022-03-15 10:28:01 +08:00
    @mikulch 加一块垃圾显卡 GPU 加速 能显著提升效率
    lakehylia
        19
    lakehylia  
       2022-03-15 10:33:11 +08:00
    软解软编非常吃 CPU ,上显卡吧。四路泰坦~~ [狗头]
    raysonlu
        20
    raysonlu  
       2022-03-15 10:36:07 +08:00
    云服务不香?
    nicevar
        21
    nicevar  
       2022-03-15 10:48:44 +08:00
    学习一下 twitch
    LLaMA2
        22
    LLaMA2  
       2022-03-15 11:13:44 +08:00
    解码 /编码确实很消耗 CPU ,这是 GPU 更擅长的领域,不过还有更专用的解码 /编码硬件,
    JAVA 层的优化空间,我能想到的是你使用的 FFMPEG 是 JAVA 实现还是 JNI/JNA 实现,
    理论上说 C++的实现会比 JAVA 的性能更好。还有你说的 API 处理是处理什么,加水印还是其他的
    图形识别?获取甲方的摄像头比你想象的更强大。你可以再展开说一说,我们的智慧是无穷的
    janus77
        23
    janus77  
       2022-03-15 11:44:51 +08:00
    吃资源的东西,还非要用 java ,这就不好弄了,要么找一下商用的,或者上云吧。云端转了传回你,你负责分发就行了
    mikulch
        24
    mikulch  
    OP
       2022-03-15 12:11:51 +08:00
    @locoz
    @ye4tar
    是一个百度的图片识别 api ,主要标注和统计当前图片中有哪些类型的车辆,和车辆所在图片的坐标的。
    mikulch
        25
    mikulch  
    OP
       2022-03-15 12:14:29 +08:00
    @andyskaura
    @ybnsjl
    @hu8245
    @ye4tar

    目前确实用的就是这个方案。java 用的是 org.bytedeco.javacv 这个库。
    mikulch
        26
    mikulch  
    OP
       2022-03-15 12:15:32 +08:00
    @janus77
    @raysonlu 感谢两位。我不太理解云服务是指?
    目前我们的项目就是部署到阿里云的。你们的意思是说,整个解码编码都不自己做了,直接把源链接扔给某个服务,然后他们转了返给我们,我们直接拿到以后分发就完事儿,连编码都不用了?
    wangyu17455
        27
    wangyu17455  
       2022-03-15 12:30:17 +08:00 via Android
    一定要拆开逐帧操作的话建议用云函数,一帧调用一次
    smilzman
        28
    smilzman  
       2022-03-15 12:51:49 +08:00
    @mikulch 可以看看 27 楼说的云函数,还有阿里云里面的 VEC 、媒体处理之类的。
    mayli
        29
    mayli  
       2022-03-15 13:01:43 +08:00
    ffmpeg 本身就可以做这个,拉取流,转码,然后推出去,一个 shell 脚本搞定
    janus77
        30
    janus77  
       2022-03-15 13:34:44 +08:00
    @mikulch #26 差不多就是这样,所有计算型的任务都是消耗云端的硬件资源。阿里云也是有类似服务的,像这种 https://www.aliyun.com/product/mts?spm=5176.100239.blogrightarea51182.6.4NU75C
    skiy
        31
    skiy  
       2022-03-15 13:52:16 +08:00
    插楼,C++ 我知道国人开发的一款比较不错的: https://github.com/ZLMediaKit/ZLMediaKit
    hu8245
        32
    hu8245  
       2022-03-15 14:01:47 +08:00
    还是交给云不错,只靠 java 很难做到高性能的音视频处理。推拉的过程带来的时延和卡顿一直都是业界研究的重点,比较靠谱的方案是推给 CDN ,这个 CDN 还是得支持 http chunck encoding 的,使用 low latency 的 DASH/HLS, 延迟能到 2s 左右,但是这都是商业方案才能做到的,开源方案基本上没有较好的办法
    LLaMA2
        33
    LLaMA2  
       2022-03-15 14:33:30 +08:00   ❤️ 1
    我仔细读了一下你补充的内容和原始的内容,由于你需要使用 opencv 做物体识别,我的建议你的 server 只处理推拉流,opencv 识别的部分放到客户 client 处理,好点的 android 设备,不带屏幕,2500 以内,用 opencv 做识别输出视频,如果甲方的摄像头能直连 android 识别的话性能更好,60FPS 没问题
    darkengine
        34
    darkengine  
       2022-03-15 14:42:13 +08:00
    先不说 CPU 使用率的问题,每帧都调用 API 怎么能保持实时性
    raysonlu
        35
    raysonlu  
       2022-03-16 09:25:17 +08:00
    @mikulch 阿里云的话,看看视频直播、视频点播提供的服务能否支持你们的整个业务流程
    zliea
        36
    zliea  
       2022-03-16 11:53:05 +08:00
    个人感觉肯定不能每帧都调用,在误差或者允许的情况下每秒调用 4-6 次足够了。
    如果必须要求每帧,我觉得需要考虑边缘计算。
    zliea
        37
    zliea  
       2022-03-16 11:56:51 +08:00
    当然非实时就随便搞了。
    mikulch
        38
    mikulch  
    OP
       2022-03-16 17:05:36 +08:00
    @zliea 刚刚新增了需求,不用实时,可以延迟 5 - 10 分钟。但是即使是这样子,问题还是存在,就是消费端看视频,看完推送过去的视频以后,就要等后续新推送的视频了。
    但是这边推送因为要走 api 处理推送会很慢,没有办法。
    mikulch
        39
    mikulch  
    OP
       2022-03-16 17:11:17 +08:00
    @darkengine 现在的问题就是这个,消费端的速度太快,生产端的速度跟不上。
    darkengine
        40
    darkengine  
       2022-03-16 17:28:05 +08:00
    所以这个方案有问题啊,搞个本地的 SDK 还差不多。
    zliea
        41
    zliea  
       2022-03-16 18:04:28 +08:00
    1. 不是每一帧数据都请求 API 。
    2. 并发请求 API ,要求 API 可以并发执行,然后等待固定延迟后再推数据。
    一个直播流就需要这么大的计算量,有没有考虑同时多个直播流,如果有趁早考虑边缘计算。
    mikulch
        42
    mikulch  
    OP
       2022-03-16 18:09:08 +08:00
    @zliea 并发请求 api 的话如何保证帧数返回的顺序呢?
    另外不是每一帧都请求的话,因为数据这边要做标注,如果不每一帧都请求的话,画面上就会出现上一帧标注了,下一帧不标注的情况,这样就感觉很奇怪。

    等待固定延时后再推送和一帧一帧的好像都差不多哇。速度还是那么慢。
    zliea
        43
    zliea  
       2022-03-16 18:30:04 +08:00
    1. 每一帧做一个标记 request id ,API 返回的时候把标记 request id 也要返回回来,然后重排。
    2. “不是每一帧数据都请求 API”,这个意味着标注不更新,就是假定每 4 帧取第 1 帧计算,那么 2-4 帧的标注也是第 1 帧的标注去合成。
    mikulch
        44
    mikulch  
    OP
       2022-03-16 18:52:58 +08:00
    @zliea 明白了,就是 2-4 帧都用第一帧的标注这个如果业务上要求,视频中的某一张图片上如果出现新的物品,需要标注出来。
    如果没标注出来的话,继续用下一个 4 帧的第一帧的标注来解决这个思路吗?这样子有图片在 4 个帧间隔之间出现又消失,不然好像没啥问题。似乎确实是个好办法,大佬有在业务上使用过这种做法吗,实际观看的时候会有啥效果影响吗?


    另外第一点确实是个好方法,相当于一个线程拉取了再一个一个的处理,确实可以节约一些 io 等待的时间。谢谢大佬。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3428 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 37ms · UTC 11:20 · PVG 19:20 · LAX 03:20 · JFK 06:20
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.