RTSP 媒体协议流的录制方案及其覆盖策略详解

news2024/11/26 0:36:56

前言

在安防和监控领域,RTSP 媒体协议流有很广泛的使用。本文将介绍一种针对 RTSP 媒体流的录制方案及其相应的覆盖策略。据我所知,声网的实时录制功能支持三种模式,分别是云端录制、本地服务端录制和页面录制,今天我们介绍的录制方案和声网的云端录制类似。

正文

本文将从录制视频格式的调研、录制方案的选择、异常状况的处理、覆盖策略的执行四个大方面进行介绍。

1. 录制视频格式调研

如果想要实现 RTSP 媒体流的录制功能,就需要考虑录制目标文件的格式,也就是把媒体流录制成哪种格式的视频文件。起初我们预设了三种方案,经过一系列调研后,最终选择了 m3u8。接下来,我们简单介绍一下这个选择过程。

1.1 为什么不用 mp4 格式

mp4 是点播视频中最为常见的视频格式,综合分析下来并不符合我们的使用场景。一般情况下,一个电影视频的最大时长也就两到三个小时左右,保存成一个 mp4 文件就够用了,但是在安防和监控场景下,一个摄像头对应的录制视频文件的长度可能是十几个小时,甚至是十几天。所以,对比下来,mp4 格式更适用于电影网站。

这就引出了 mp4 格式的一个缺点,如果录制存储为一个 mp4 格式,那文件体积可能会非常大。那么,存储的时候就会面临一系列问题,比如磁盘空间不足、大文件分片等状况的处理,特别是录制过程中数据流异常中断可能会导致已经录制的 mp4 文件不可用,这是其一。

我们知道 mp4 文件是由许多 Box 和 FullBox 组成的,可以参考上图的 Box 树形图,其中,FullBox 是 Box 的扩展,每个 Box 又包含 Header 和 Data 两部分,moov Box 记录了整个 mp4 文件的音视频媒体信息。而 moov Box 一般是在 mp4 文件写完时才在文件尾部添加。因此,又引出了另外一个缺点,如果 mp4 文件特别大,那么在播放的时候,播放器需要加载全部的视频文件到内存中,如果视频文件特别大,这几乎是不现实的。因此,我们在录制结束保存 mp4 的时候,需要把 moov Box 调整到文件头部来避免这个问题。

文末名片可以免费领取音视频开发学习资料,内容包括(C/C++,Linux 服务器开发,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)以及音视频学习路线图等等。

见下方↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

1.2 为什么不用 mpd 格式

mpd 格式类似于 m3u8 格式,但是它采用的是 XML 的组织形式。我们不选择它的原因也有两个,其一,mpd 格式在现有产品线上没有类似使用场景,我们使用更多的是 m3u8,换句话说就是技术储备不足。

其二,播放器方案的通用性上存在问题,如果使用 mpd 格式,那么我们的播放器方案需要调整,能够支持 mpd 格式媒体的播放,这样一来会给播放器带来一定的工作量和隐含的问题。

最后,给出一个 mpd 的文件示例,让大家对其有一个更加直观的了解。

<?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version 97fc982-release-->
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="static" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT734S">
  <Period id="0">
    <AdaptationSet id="0" contentType="audio" lang="en">
      <Representation id="0" bandwidth="131596" codecs="mp4a.40.2" mimeType="audio/mp4" audioSamplingRate="44100">
        <AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
        <BaseURL>tears_audio_eng.mp4</BaseURL>
        <SegmentBase indexRange="745-1664" timescale="44100">
          <Initialization range="0-744"/>
        </SegmentBase>
      </Representation>
    </AdaptationSet>
    <AdaptationSet id="1" contentType="video" maxWidth="1920" maxHeight="856" frameRate="12288/512" par="38:17">
      <Representation id="1" bandwidth="769255" codecs="avc1.42c01e" mimeType="video/mp4" sar="852:857" width="320" height="142">
        <BaseURL>tears_h264_baseline_240p_800.mp4</BaseURL>
        <SegmentBase indexRange="827-1602" timescale="12288">
          <Initialization range="0-826"/>
        </SegmentBase>
      </Representation>
      <Representation id="2" bandwidth="1774254" codecs="avc1.4d401f" mimeType="video/mp4" sar="2242:2249" width="854" height="380">
        <BaseURL>tears_h264_main_480p_2000.mp4</BaseURL>
        <SegmentBase indexRange="829-1604" timescale="12288">
          <Initialization range="0-828"/>
        </SegmentBase>
      </Representation>
      <Representation id="3" bandwidth="7203938" codecs="avc1.4d4028" mimeType="video/mp4" sar="855:857" width="1280" height="570">
        <BaseURL>tears_h264_main_720p_8000.mp4</BaseURL>
        <SegmentBase indexRange="830-1605" timescale="12288">
          <Initialization range="0-829"/>
        </SegmentBase>
      </Representation>
      <Representation id="4" bandwidth="18316946" codecs="avc1.64002a" mimeType="video/mp4" sar="856:857" width="1920" height="856">
        <BaseURL>tears_h264_high_1080p_20000.mp4</BaseURL>
        <SegmentBase indexRange="832-1607" timescale="12288">
          <Initialization range="0-831"/>
        </SegmentBase>
      </Representation>
    </AdaptationSet>
  </Period>
</MPD>

通过上述文件,我们可以知道这个 mpd 文件包含了一路音频流,同时支持三种不同分辨率和码率的视频流。不同的媒体类型是用 AdaptationSet 标签表示的,内部还可以使用 Representation 标签标记不同分辨率和码率的媒体流。

1.3 为什么最终选择 m3u8 格式

选择 m3u8 的话,优势就会更加明显,除了规避上述方案的问题外,还有一些自身的优势,具体表现如下:

  1. 本身就是 ts 分片存储形式,不需要再单独考虑大文件的切片问题。

  2. 现有播放器方案支持 m3u8 格式,不需要再单独进行适配。

  3. 具有一定的技术储备,开发上手快,开发周期可控。

  4. 相应的覆盖策略执行起来会更加方便。

最后,给出一个 m3u8 的文件示例,让大家对其有一个更加直观的了解。

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:17
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:11.933333,
index_0000.ts
#EXTINF:3.866667,
index_0001.ts
#EXTINF:7.333333,
index_0002.ts
#EXTINF:16.666667,
index_0003.ts
#EXTINF:4.133333,
index_0004.ts
#EXT-X-ENDLIST

通过上述文件,我们可以知道这个 m3u8 文件包含了 5 个 ts 分片,以及它们各自的时长信息。文件以 #EXTM3U 标签开始,并以 #EXT-X-ENDLIST 标签结束。这里有一点需要注意,如果是直播使用的 m3u8 文件,它是没有 #EXT-X-ENDLIST 标签的。

2. 录制方案选择

既然已经确定了目标文件的格式,那么我们就要考虑怎么实现了。目前有两个方案可以考虑,一个是 Golang 纯原生方案,另一个是利用 ffmpeg 实现,接下来分别介绍。

2.1 Go 原生

利用纯原生的 Golang 实现,其实,Golang 处理音视频数据还是有一定优势的,通过解封装 RTSP 媒体流,得到音频数据和视频数据,然后创建对应的解码器,得到对应的原始音频 PCM 数据和原始视频 YUV 数据,再分别编码成 AAC 的音频和 H264 的视频,最后保存成 m3u8 格式的录制文件。整个过程可以参考下图:

这种方案,编码的工作量会稍微大一些,同时有很多音视频数据处理的细节问题,负载度和难易程度上不如 ffmpeg 方案。

2.2 ffmpeg

利用 ffmpeg 工具库,通过启用 ffmpeg 进程来完成对应的 RTSP 流数据接收和 m3u8 文件录制保存工作,这样会更加简单,我们只需要管理好进程的创建、释放和异常处理工作。

3. 异常处理

录制过程中会遇到各种各样的问题,接下会分别介绍。有一点是相同的,所有的异常状况都会通知到录制调度服务,由调度服务进行统一分析和管理,同时支持热备机制,我们通过 Nacos 的服务发现机制监测录制调度服务的运行状态,具体关系可以参考下图:

3.1 CPU、磁盘

CPU 负载过高和磁盘空间不足是最为常见的两种录制时的异常状况,大致的处理逻辑也是较为相似的。

CPU 过高的处理逻辑,可以参考下图:

当前机器接收到任务后,进行自检操作,发现 CPU 负载过高会停止当前录制任务的执行,同时上报调度服务,重新分配别的机器执行该录制任务。

当前机器正在执行录制任务,突然发现 CPU 负载超过阈值,会持续观察一段时间,假定观察周期为 10 秒,如果 CPU 负载连续 10 秒钟超高,那么会停止当前录制任务,同时上报调度服务,请求别的机器继续执行该录制任务,最后将两台机器上的录制文件进行逻辑关联保存到数据库中。如果 CPU 负载在 10 秒内恢复到正常值,我们将继续执行当前录制任务。

磁盘空间不足的处理逻辑和 CPU 负载过高有类似的处理逻辑,具体可以参考下图:

通过流程图,我们也可以知道磁盘空间不足的处理逻辑和 CPU 负载过高时类似,上图已经展示的非常明确了,这里就不过多赘述了。

3.2 异常处理

一些其他的异常处理情况,比如崩溃,整体流程可以参考下图:

异常发生时,如果是一般异常,我们只需要将状态通知调度服务即可,调度服务记录相关日志,综合分析整个录制服务的状态。如果 60%的录制机器触发了相同的异常,调度服务就要采取相应的策略。如果是崩溃等重大异常,就需要重启机器或者调度新的机器继续执行录制任务。

3.3 录制超时

如果发生了录制超时,比如我们想录制 24 个小时的视频,现在时长已经录够了,接下来应该怎么做呢?一般有两种处理方法,第一种是直接停止当前录制,上报通知调度服务即可,这种处理方式比较简单粗暴,但是在安防和监控领域是不合适的。第二种是执行特定规则的覆盖策略,实现循环覆盖,始终保留最近 24 小时之内的视频画面内容。

对比上述两种处理方式,当发生录制超时时,第二种方式是最符合安防和监控领域的通用做法。那么覆盖策略又是怎么实现的呢,这就引出了下面的内容——覆盖策略。

4. 覆盖策略

覆盖策略在原理上理解起来很简单,但是具体执行时,就不那么简单了。首先,我们也先通过一个流程图对覆盖策略的处理逻辑有一个整体上的认识。

4.1 一级定时器

当录制任务启动时,我们同时启动一个定时器(一级定时器),定时器的时长就是录制任务的目标时长,这个非常好理解。但是,这个定时器只生效一次或者一次都不生效。只有一级定时器生效后,才会启动二级定时器。如果一级定时器没有启动,那么二级定时器也不会启动。

我们可以这样理解,只有一级定时器触发,录制服务才会执行对应的覆盖策略。当覆盖策略启动后,一级定时器销毁,二级定时器生效。

4.2 二级定时器

当文件时长达到了预设的最大时长时,我们将启动二级定时器。其实,二级定时器控制的是覆盖策略的删除频率,每次时间到了,就删除早些时候到录制文件分片。

4.3 执行覆盖

具体覆盖的执行逻辑是,根据 ts 分片的时长和二级定时器的时间周期,计算需要删除的 ts 分片个数,同时更新 m3u8 中的索引列表,然后循环执行该策略,最终实现动态循环的录制覆盖策略。

覆盖策略的执行过程如上图所示,相信通过上文的解释,大家理解起来还是非常容易的。需要特别说明的是,由于二级定时器执行周期 t 的限制,录制文件的实际时长在最大录制时长 T 和(T+t)之间。

结尾

好了,现在关于 RTSP 媒体流的录制方案和覆盖策略就介绍完了,相信大家对云端录制方案也有了一定认识,有自己想法和感兴趣的小伙伴,欢迎评论留言。关注我,分享更多音视频和流媒体服务器内容。

作者:刘振
原文链接:https://cloud.tencent.com/developer/news/824356

文末名片可以免费领取音视频开发学习资料,内容包括(C/C++,Linux 服务器开发,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)以及音视频学习路线图等等。

见下方↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/84005.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[基因遗传算法]进阶之六:VRP的进阶经典问题的解码如何写

文章目录一、CVRP二、MDCVRP2.1 解的编码分析2.2 代码2.3 分割展示三、VRPTW四、MDVRPTW4. 1 解的编码分析4.2 解的代码4.3 结果展示4. 4 MDVRPTW的计算适应度4.5 MDVRPTWd的结果展示图一、CVRP 见博文《[基因遗传算法]进阶之三:实践CVRP》 二、MDCVRP 参考资料:《Python实现…

Qt的场景图Scene Graph

叫场景树更合适&#xff0c;本质不是图。QML场景中的Qt Quick项目将填充QSGNode实例树。 场景图是Qt Quick 2.0引入的&#xff0c;建立在要绘制的内容是已知的基础上。所有QML项目均使用场景图进行渲染&#xff0c;场景图的默认实现是与OpenGL紧密相关的低级高性能渲染堆栈。 …

谈谈前端性能优化-面试版

前言 当我们去面试的时候&#xff0c;很大概率会被面试官问这么一个问题&#xff1a;你有尝试过对项目做性能优化吗&#xff1f;或者你了解哪些性能优化的方法&#xff1f;听到这个问题的你可能是这样的&#xff1a; 似曾相识但又说不清楚&#xff0c;往往只能零散地说出那么几…

Go string原理简析

引入 当查看string类型的变量所占的空间大小时&#xff0c;会发现是16字节&#xff08;64位机器&#xff09;。 str : "hello"fmt.Println(unsafe.Sizeof(str)) // 16也许你会好奇&#xff0c;为什么是16字节&#xff0c;它的底层存储模型是什么样子的。 源码分析 …

焦脱镁叶绿酸-a修饰量子点/荧光/药物/小分子抑制剂/上转换纳米颗粒/树枝状聚合物

小编在这里为大家分享的科研内容是焦脱镁叶绿酸-a修饰量子点/荧光/药物/小分子抑制剂/上转换纳米颗粒/树枝状聚合物的相关研究&#xff0c;来看&#xff01; 焦脱镁叶绿酸-a简介&#xff1a; 焦脱镁叶绿素-a是产物叶绿素a通过脱甲氧羰基、去植物醇、去Mg后的产物。该类物质具有…

day19【代码随想录】删除字符串中的所有相邻重复项、逆波兰表达式求值、滑动窗口最大值、前 K 个高频元素、数组中的第K个最大元素

文章目录前言一、删除字符串中的所有相邻重复项&#xff08;力扣047&#xff09;二、逆波兰表达式求值&#xff08;力扣150&#xff09;三、滑动窗口最大值&#xff08;力扣239&#xff09;四、前 K 个高频元素&#xff08;力扣347&#xff09;五、数组中的第K个最大元素&#…

MyBatis系列---crud返回值

目录1. service与mapper2. 更新操作3. 查询操作3.1. 返回值存储3.2. 简单映射3.3. ResultSet 的预处理3.4. 确定 ResultMap3.5. 创建映射结果对象3.6. 自动映射3.7. 存储对象3.8. 返回结果为单行数据3.9. 返回结果为多行数据3.10. 结论1. service与mapper mybatis一般与spring…

深度活体模型带交互模型版

🍿*★,*:.☆欢迎您/$:*.★* 🍿

点击Tab标签切换不同查询数据,并选择数据存入缓存实现两个界面带参数跳转

项目场景&#xff1a; 在不同的tab标签页中点击不同的标签页查找不同的内容,然后选中其中一个页面中的一条数据将此数据某个信息选中然后存入session缓存当中然后另一个界面从session中取出,从而达到带参数跳转界面的需求 问题描述 可以做到跳转界面但是数据会显示到地址栏当…

做开发4年了,年薪还不如2年经验的测试。我该适应当下节奏吗...

代码码了这么些年&#xff0c;你年薪达到多少了&#xff1f; 我&#xff0c;4年码龄&#xff0c;薪资最高的时候16k*12薪&#xff0c;年薪不到20W。都说IT行业薪资高&#xff0c;但年薪百万的还是金字塔尖极少数&#xff0c;像我这样的才是普通的大多数&#xff0c;却也还要用…

电脑维护与故障处理

第一章 认识电脑的组成 1.1 硬件组成 1.1.1 CPU 1.1.2 主板 1.1.3 内存 1.1.4 硬盘 1.1.5 电源 1.1.6 显示器 1.1.7 键盘和鼠标 1.1.8 光驱 1.1.9 显卡 1.1.10 其他外部设备 1.2 软件组成 1.2.1 操作系统 Windows XP Windows 7 服务器操作系统 —— Windows Ser…

04-Nginx-conf配置文件基本了解

Nginx负载均衡&#xff0c;反向代理入门配置&#xff1a; nginx.conf整体结构 nginx入门基本配置 Nginx.conf配置文件详解&#xff08;upstream和location负载均衡和反向代理配置&#xff09;&#xff1a; #运行用户 user www-data; #启动进程,通常设置成和cpu的数量相等 wor…

基于边缘智能网关打造智慧体育场

运动健身是民众广泛存在的生活需求&#xff0c;体育场馆作为承载各种体育运动的基础设施&#xff0c;其运营管理效率、服务水平和智能化场景应用等都与用户体验紧密相关。 得益于物联网、边缘计算、AI智能等新技术的广泛应用&#xff0c;当前已有越来越多体育场馆通过部署基于…

数据结构与算法——Java实现稀疏数组和队列

目录 一、基本介绍 1.1 线性结构 1.2 非线性顺序结构 二、稀疏数组 2.1 基本介绍 2.1.1 应用场景 2.1.2 实现思路 2.2 代码实现 2.2.1 原始数组 2.2.2 原始数组转化为稀疏数组 2.2.3 稀疏数组转化为原始数组 三、队列的应用场景和介绍 3.1 数组模拟队列 3.1.1数组模拟队列的…

Find My资讯|Seinxon推出支持苹果 Find My 防丢卡

在美国&#xff0c;平均每个人每年丢失 3,000 件物品。而在 2021 年&#xff0c;Pixie 数据显示&#xff0c;丢失产品的更换成本超过 25 亿美元。每周超过两次&#xff0c;将近 1/4 的美国人丢失房门钥匙、钱包、宠物、电话、眼镜、耳机、遥控器、手提箱或孩子最喜欢的物品。 …

GIT系列(七)切换ssh连接,上传不再输入账号、密码

文章目录前言操作流程前言 使用HTTP连接方式时&#xff0c;上传代码总是需要登录&#xff0c;键盘都打坏了&#xff0c;切换SSH可以无需密码&#xff0c;直接上传。 操作流程 step 1 确保在git服务器已经部署本机公钥。 没有配置SSH的&#xff0c;戳这里 GIT系列&#xff08;…

k8s教程(18)-pod之DaemonSet(每个node上只调度一个pod)

文章目录01 引言02 DaemonSet2.1 应用场景2.2 举例2.3 注意事项03 文末01 引言 声明&#xff1a;本文为《Kubernetes权威指南&#xff1a;从Docker到Kubernetes实践全接触&#xff08;第5版&#xff09;》的读书笔记 DaemonSet是 Kubernetes1.2 版本新增的一种资源对象&#xf…

事件轮询机制 Event Loop、浏览器更新渲染时机、setTimeout VS setInterval

目录 1. 事件轮询机制&#xff08;Event Loop&#xff09;是什么 1.1 宏任务、微任务 1.2 Event Loop 循环过程 1.3 经典题目分析 1.3.1 第一轮事件循环 1.3.2 第二、三次事件循环 1.3.3 参考文章 2. async、await 在事件轮询中的执行时机 3. 浏览器更新渲染时机、Vue…

线上使用雪花算法生成id重复问题

项目中使用的是hutool工具类库提供的雪花算法生成id方式&#xff0c;版本使用的是5.3.1 <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.3.1</version></dependency>雪花算法生成id…

10分钟数仓实战之kettle整合Hadoop

1.写在前面 很多朋友在做数仓的ETL的动作的时候&#xff0c;还是喜欢比较易上手的kettle 前面章节有介绍过安装kettle&#xff0c;可以参考 ETL工具--安装kettle_老码试途的博客-CSDN博客_spoon.bat 安装 kettle在Windows系统中对数据的转换、表和文件的转换等&#xff0c;…