智能小车开发篇 - 低时延直播测试

· 浏览次数 : 0

小编点评

智能小车开发篇 - 低时延直播测试 一、前言 市面上常见的推拉流协议有:RTMP、HLS、HTTP-FLV、RTSP、WebRTC等。本章节暂不考虑服务器性能指标,目前仅对核心开发板资源占用、延时作为硬性考虑指标。 二、协议名称及优势劣势 | 协议名称 | 延时 | 传输协议优势 | 传输协议劣势 | 适用场景 | | ------- | ---- | ------------ | ------------ | -------- | | RTMP | 1~5s | 协议成熟 | 上手成本低 | PC 端延时不敏感直播 | | HLS | >10s | 点播场景非常适用 | 平滑播放(像播放视频文件一样直播)延迟非常高 | 点播场景 | | HTTP-FLV | 1~5s | 延时较低且可浏览器播放 | 浏览器上适用需要用到特定播放器(flv.js)对延时有一定要求并期望在浏览器上播放的场景 | | RTSP | <1s | 延时极低属于被动协议,需要客户端主动去拉流 | 不会向外推流(GB28181 可以实现向外推流) | 大家摄像头厂商基本协议 | | WebRTC | <500ms | 延时很低 | 上手难度大 | 低时延直播、会议室 | 三、实验与测试 1. 核心开发板:树莓派 4B、Raspberry 4B (4G 版本)摄像头:树莓派官方 CSI 接口摄像头 1280x720操作系统:ubuntu server 22.04LTS相关软件:GStreamer、SRS服务器相关资源容器:Docker流媒体服务器:SRS5.0监控:Prometheus + Grafana环境安装与部署相关环境安装的教程建议参考官方文档。 2. 推流方式 - 方案一:RTMP 推流 + RTMP 拉流 使用 GStreamer 推流,推流前系统资源占用较低,但拉流时间较高。 - 方案二:RTMP 推流 + HTTP-FLV 拉流 使用 GStreamer 推流,效果还行,普通低延时场景够用,如果做远程控制则还是不太足够。 - 方案三:RTMP 推流 + WebRTC 拉流 使用 GStreamer 推流,效果不错,但挪到公网上还有待考究。 四、测试小结 1. 推流方式:GStreamer - RTMP,KMPlayer - RTMP,FFmpeg - RTMP,资源占用较低,但拉流时间较高。 2. 推流方式:GStreamer - HTTP-FLV,KMPlayer - RTMP,FFmpeg - RTMP,效果还行,普通低延时场景够用,如果做远程控制则还是不太足够。 3. 推流方式:GStreamer - WebRTC,KMPlayer - RTMP,FFmpeg - RTMP,效果不错,但挪到公网上还有待考究。 五、结论 如果双端都能做到走 WebRTC 的方案,延时会更小更稳定一些吧;如果是普通场景,我觉得我去先择 RTMP + HTTP-FLV 已经十分足够了,但是目前需要做远程控制,而且还需要做到外网控制的话, WebRTC 是一个不错的选择。

正文

智能小车开发篇 - 低时延直播测试

本章节暂不考虑服务器性能指标, 目前仅对核心开发板资源占用、延时作为硬性考虑指标

前言

目前市面上常见的推拉流协议有:RTMP、HLS、HTTP-FLV、RTSP、WebRTC

协议名称 延时 传输协议 优势 劣势 适用场景
RTMP 1~5s TCP 1. 协议成熟
2. 上手成本低
兼容性问题,大部分主流浏览器已不支持 Flash PC 端延时不敏感直播
HLS >10s TCP 1. 点播场景非常适用
2. 平滑播放(像播放视频文件一样直播)
延迟非常高 点播场景
HTTP-FLV 1~5s TCP 1. 延时较低且可浏览器播放 浏览器上适用需要用到特定本播放器(flv.js) 对延时有一定要求并期望在浏览器上播放的场景
RTSP <1s TCP/UDP 1. 延时极低
属于被动协议,需要客户端主动去拉流,不会向外推流(GB28181 可以实现向外推流) 各大摄像头厂商基本协议
WebRTC <500ms UDP 1.延时很低 上手难度大 低时延直播、会议室

上述的表格统计也仅为本人经验总结,欢迎大佬们指正与指点迷津。😀😀

🚩 上述延时均为大概范围,具体时间还得看不同的拉流手段、服务器环境、网路环境等因素。

🔶🔶 题外话:

本人项目中也试过这样的推拉流方案:

  • 推流端: RTSP
  • 拉流端: JSMpeg
  • 中转端: FFmpeg

整个流程:RTSP -> FFmpeg -> JAVA 服务 -> WebSocket -> 客户端

FFmpeg 拉取 RTSP 流,转码并转成 TCP 流至 JAVA 服务,JAVA 服务将接收到的流通过 WebSocket 推送至浏览器客户端;客户端接收后利用 JSMpeg 来播放整个流

当初这样处理主要是为了少搭建一个流媒体服务器,一般情况下我还是会去选择转 RTMP 后适用 flv.js 播放

相关资源

本次实验与测试对象如下

  • 核心开发板:树莓派 4B Raspbarry 4B (4G 版本)
  • 摄像头:树莓派官方 CSI 接口摄像头 1280x720
  • 操作系统: ubuntu server 22.04LTS
  • 相关软件: GStreamer

服务器相关资源

  • 容器: Docker
  • 流媒体服务器: SRS5.0
  • 监控: Prometheus + Grafana

环境安装与部署

相关环境安装的教程建议参考官方文档(好的项目总是不断更新迭代的,经常翻阅文档将会是一个不错的习惯)

测试方案

目前由于学习成本与时间关系:仅从以下几种低成本的方式进行选择性测试,后续再发文其他方式的相关文章。

由于对延时的要求较高,因此目前暂不考虑 HLS 这等高延时方案,RTSP 由于是一个被动拉取的协议,因此也暂时不考虑 RTSP 的方案,WebRTC 方案技术成本较高,放后续进行测试与整理文档。

  1. RTMP 推 - HTTP-FLV 拉
  2. RTMP 推 - WebRTC 拉
  3. 自定义格式 UDP 推流 - 自定义 UDP 拉流

基本资源占用情况

基本资源占用情况
如上图所示,在未进行任何推流的情况下资源占用

  • CPU:<= 1.5%
  • 内存:<= 9.6%
  • 网络:~= 0 kb/s

开发板中仅运行了:node_exporter 用于监控开发板资源

SRS 配置文件

由于是内网环境,目前下属文件配置环境中的 candidate 设置的 ip 为我局域网 ip

# main config for srs.
# @see full.conf for detail config.

listen              1935;
max_connections     1000;
#srs_log_tank        file;
#srs_log_file        ./objs/srs.log;
daemon              on;
http_api {
    enabled         on;
    listen          1985;
}

http_server {
    enabled         on;
    listen          8080;
    dir             ./objs/nginx/html;
    #这里开启了跨域允许
    crossdomain on;
}

rtc_server {
    enabled on;
    listen 8000; # UDP port
    # @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#config-candidate
    candidate 192.168.108.9;
}

vhost __defaultVhost__ {
    enabled on;
    tcp_nodelay on;
    min_latency on;

    hls {
        #暂不适用hls,不做开启
        enabled     off;
    }

    http_remux {
        enabled     on;
        mount       [vhost]/[app]/[stream].flv;
    }

    rtc {
        enabled     on;
        nack on;
        rtmp_to_rtc on;
        twcc on;
    }

    play{
        gop_cache off;
        queue_length 10;
        mw_latency 350;
    }

    publish{
        mr on;
        mr_latency 350;
    }
}

方案一:RTMP 推流 + RTMP 拉流

GStreamer 推流

推流前系统资源占用情况

此时设备刚开机,CPU 占用~=40%,查看了一下进程,发现是自动更新了某些东西

因此等待更新完成后再做下列操作

推流前系统资源占用情况

img

  • CPU:~= 1%
  • 内存:~= 10%
  • 网络:~= 0 kb/s

开始推流

推流指令

gst-launch-1.0 -v v4l2src device=/dev/video0 ! 'video/x-h264, width=1280, height=720, framerate=30/1' ! h264parse ! flvmux ! rtmpsink location='${ip}'

推流了大概 5 分钟后延时图
推流效果图

推流资源占用情况

img

时机 CPU 内存 网络
推流前 1% 10% 0 kb/s
推流后 2.5% 10.3% 60 kb/s ~ 7 Mb/s

推流直播延时

  • 实际时间: 10:14:15:069
  • 显示时间: 10:14:13:600
  • 相差延时: 1.3s 左右

本次推流大概使用的资源如下

  • CPU:~= 1.5%
  • 内存:~= 3M 左右
  • 网络:60 kb/s ~ 7 Mb/s(具体看画面变化)

小总结

总的看来,使用 GStreamer 推流时带宽使用的较为大外,资源占用情况还是比较低的

我们其实可以看到 Network Traffic Basic 这一栏的波动,前一段是一个平缓的数值,突然间上涨到一个高度,然后再后续下降下来,最后呈现出一个很低的平缓直线

一开始我还在好奇,怎么流量上涨了这么多?我好像也没处理什么,还以为有什么其他程序增高了这个

但后想了以下,也没开其他应用程序;

然后怀疑是 H.264 传输压缩的问题, 测试了一下,当我将摄像头摆在一个画面丰富且动态变化的情况下,此时网络占用非常高;当我将摄像头盖起来(基本上处于一个黑色不变的情况下),此时网络占用几近于无(~=60 kb/s)

做了这个实验其实已经证实了我的想法, H.264 编码里面会使用 I帧P帧B帧 来组成画面与减少数据体积;[1]

当我们画面几乎不变时 使用 P帧B帧 编码是数据体积会很小,因此节省了很多的带宽资源。

FFmpeg 推流

推流前系统资源占用情况

推流前先用了 echo 3 > /proc/sys/vm/drop_caches 命令清空了 buff/cache

此时系统占用情况

img

  • CPU:~= 1.3%
  • 内存:~= 9.5%
  • 网络:~= 0 kb/s

开始推流

推流指令

ffmpeg -f v4l2 -framerate 30 -video_size 1280x720 -i /dev/video0 \
       -c:v libx264 -preset veryfast -maxrate 1000k -bufsize 2000k -pix_fmt yuv420p \
       -c:a aac -b:a 128k -ar 44100 \
       -f flv ${ip}

推流了大概 5 分钟后延时图

img

系统资源占用情况
img

时机 CPU 内存 网络
推流前 1.3% 9.5% 0 kb/s
推流后 58.2% 14.3% 600 kb/s

推流直播延时

  • 实际时间: 10:30:24:387
  • 显示时间: 10:30:21:533
  • 相差延时: 3s 左右

本次推流大概使用的资源如下

  • CPU:~= 58%
  • 内存:~= 140M 左右
  • 网络:600 kb/s

小总结

这里可以看到与 Gstreamer 推流相比,FFmpeg 推流下系统资源占用,延时等明显上升了一个台阶,但是带宽稳定在 600 kb/s

这里应该是对整个视频流进行了压缩处理导致需要较多的 CPU 资源与 内存占用(目前还没熟悉 FFmpeg 的相关参数,后续对其学习后整理相关的文档在过来重新分析对此进行分析)

章节总结

推流方式 延时 CPU 占用 内存占用 带宽占用
GStreamer 1.3s 1.5% ~=3M 60 kb/s ~ 7 Mb/s(具体看画面变化)
FFmpeg 3s 58% ~=140M 600 kb/s

上面的总结测试并不完整与科学;明显能得出的是 FFmpeg 应该会去压缩画面从而减少带宽,但与之相对应的是系统资源的占用提升;目前由于我们第一要义是选择资源占用小的,延时低的,暂时先选择用 GStreamer 来进行推流;(欢迎各位大佬来帮忙解答这部分)

方案二:RTMP 推流 + HTTP-FLV 拉流

由于推流在方案一里已经做了对比效果,因此本方案只使用 GStreamer 进行推流;然后只针对于 HTTP-FLV 拉流的方式进行查看延时效果

拉流效果图

img

  • 实际时间: 10:52:01:173
  • 显示时间: 10:52:00:289
  • 相差延时: 1s 左右

总的来说效果还是出乎我的意料的;看上去延时不是特别高,而且最主要还能直接通过浏览器进行播放;

方案二:RTMP 推流 + WebRTC 拉流

由于推流在方案一里已经做了对比效果,因此本方案只使用 GStreamer 进行推流;然后只针对于 WebRTC 拉流的方式进行查看延时效果

拉流效果图

img

  • 实际时间: 10:55:03:620
  • 显示时间: 10:55:03:452
  • 相差延时: 200ms 左右

这个局域网拉流的实际效果已经非常不错了,基本上可以算是一个比较实时的反馈了。当然其实 WebRTC 还是一个比较庞大且复杂的东西,里面还需要我更深入的去研究才能做出更好的选择。

测试小结

推流方式 拉流方式 延时 备注
GStreamer - RTMP KMPlayer - RTMP 1.3s 资推流资源占用较低,但拉流时间较高
FFmpeg - RTMP KMPlayer - RTMP 3s 资源占用较高,
GStreamer - RTMP HTTP-FLV 1s 效果还行,普通的低延时场景够用,如果做远程控制则还是不太足够
GStreamer - RTMP WebRTC 200ms 效果不错,但挪到公网上还有待考究

最后的总结:

如果双端都能做到走 WebRTC 的方案,延时会更小更稳定一些吧;
如果是普通场景,我觉得我去先择 RTMP + HTTP-FLV 已经十分足够了,但是目前需要做远程控制,而且还需要做到外网控制的话, WebRTC 是一个不错的选择。
当然,本次实验的过程其实可以说是漏洞百出,例如:

  1. 没有对 KMPlayer 播放器是否会做其他操作来增高延时(例如SRS里面说的不要用VLC观看,VLC延时会很大[2]
  2. 也没使用自定义协议来进行传输(理论上应该延时也比较低,但是稳定性就需要看怎么去设计了)
  3. 而且很多细节没有去深究为什么,怎么做到统一从而减少误差。
    参考了很多文章,也学到了不少新的知识点,也算是稍微拓宽了我的知识面吧。

相关用到的部署命令


# Docker run Prometheus
docker run -itd -p 9090:9090 --name promethues prom/prometheus

# Docker run Grafana
docker run -d --name grafana -p 3000:3000 grafana/grafana-enterprise


参考文章

https://stackoverflow.com/questions/70655928/live-streaming-from-raspberry-pi-to-nodejs-server-hosted-on-google-app-engine/70675353#70675353
https://opensource.com/article/19/1/gstreamer
https://github.com/ossrs/srs/issues/2304
http://www.riqicha.com/beijingshijian.html


  1. https://www.cnblogs.com/Lxk0825/p/9925041.html ↩︎

  2. https://ossrs.net/lts/zh-cn/docs/v5/doc/sample-realtime ↩︎

与智能小车开发篇 - 低时延直播测试相似的内容:

智能小车开发篇 - 低时延直播测试

智能小车开发篇 - 低时延直播测试 本章节暂不考虑服务器性能指标, 目前仅对核心开发板资源占用、延时作为硬性考虑指标 前言 目前市面上常见的推拉流协议有:RTMP、HLS、HTTP-FLV、RTSP、WebRTC 协议名称 延时 传输协议 优势 劣势 适用场景 RTMP 1~5s TCP 1. 协议

华为云Astro的前世今生:用7年时间革新低代码开发观念

摘要:深扒华为云Astro低代码平台的前世今生,其成功之路显然是一条“个性”之路。 本文分享自华为云社区《华为云Astro的前世今生:用7年时间革新低代码开发观念》,作者:华为云PaaS服务小智。 2022年华为全联接大会(HUAWEI CONNECT)期间,华为云CEO张平安发布华为云Astro低

高效运营新纪元:智能化华为云Astro低代码重塑组装式交付

摘要:程序员不再需要盲目编码,填补单调乏味的任务空白,他们可以专注于设计和创新;企业不必困惑于复杂的开发过程,可以更好地满足客户需求以及业务策略迭代。 本文分享自华为云社区《高效运营新纪元:智能化华为云Astro低代码重塑组装式交付》,作者:华为云PaaS服务小智。 借着东莞仲夏微风,HDC.Clo

【单片机入门】(四)应用层软件开发的单片机学习之路-----ESP32开发板PWM控制电机以及中断的使用

引言 各位大佬,晚上好啊,在上一篇博客中,我们讲了什么是UART串口通讯,以及使用USB转TTL使得单片机可以和c#上位机做一个串口通讯,接下来,为大家带来PWM的概念原理,以及实际案例,使用PWM对电机进行速度调制,因为本课程的最后是做一个红外遥控的智能小车,所以是需要电机四个,驱动四个,轮胎四个

华为云大咖说:开发者应用AI大模型的“道、法、术”

本文分享自华为云社区《华为大咖说 | 企业应用AI大模型的“道、法、术” ——道:认知篇》,作者:华为云PaaS服务小智。 本期核心观点 上车:AGI是未来5~10年内,每个人都无法回避的技术革命,建议就近上车。 迭代:眼下的AI大模型应用都还只是过程稿,仍在快速迭代,切忌刻舟求剑。 预判:AI大模

AI Agent实战:智能检索在Kingbase数据库管理中的优势应用

虽然在开发过程中遇到了不少技术挑战,但最终我成功构建了一个针对金仓数据库的社区检索咨询助手。这个助手不仅解决了普通web搜索无法满足特定数据库问题的需求,还提高了我解决问题的效率和质量。在未来的工作中,我将继续优化这个助手,使其更加智能和强大。

ChatGPT插件开发实战

1.概述 ChatGPT是一款由OpenAI推出的先进对话模型,其强大的自然语言处理能力使得它成为构建智能对话系统和人机交互应用的理想选择。为了进一步拓展ChatGPT的功能和适应不同领域的需求,OpenAI提供了插件开发平台,让开发者可以定制化和扩展ChatGPT的能力。 2.内容 OpenAI

Visual Studio 智能代码插件:CodeGeeX

前言 在软件开发领域,高效的编程助手一直是提升开发者效率和质量的关键。随着人工智能技术的不断发展,智能编程助手逐渐成为开发者们不可或缺的工具。其中,CodeGeeX作为一款专为Visual Studio设计的免费智能编程助手,凭借其强大的功能和便捷的使用体验,赢得了广大开发者的青睐。 CodeGee

手把手实践丨基于STM32+NBIOT+华为云IOT设计智能井盖

摘要:本文介绍基于STM32微控制器、BC26 NBIOT模组和华为云IOT平台,实现了一款智能井盖系统。 本文分享自华为云社区《基于STM32+NBIOT+华为云IOT设计的智能井盖》,作者:DS小龙哥 。 一、概述 智能井盖是一种通过物联网技术实现对井盖状态监测和管理的设备。当前介绍基于STM3

Visual Studio 必备插件集合:AI 助力开发

一、前言 2024年AI浪潮席卷全球,编程界迎来全新的挑战与机遇。智能编程、自动化测试、代码审查,这一切都得益于AI技术的迅猛发展,它正在重塑开发者的日常,让编写代码变得更加高效、智能。 精选出最受好评、最具实用价值的Visual Studio插件,涵盖代码编辑、调试、测试、版本控制等多个方面,帮助