关于hls切片和rtmp视频源的gop有关

本文探讨了Group of Picture (GoP) 大小对视频直播的影响,包括对RTMP和HLS两种主流协议的首屏加载速度和延迟的具体影响,并提出了针对不同应用场景的优化建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二.GoP性能调优分析

Group of Picture(以下简称GoP)顾名思义就是有一组帧组成的一个序列。Wikipedia上给出的一个图简单的解释了GoP是怎么回事(见图二):
图二
GoP由I帧开始,后面跟随者一组B帧和P帧,直到下一个I帧之前的帧为一个GoP。了解了GoP之后,就会发现播放器只有在拿到某个GoP中的I帧之后才能播放视频。对于GoP来说,编码器都是可以进行设置的,像OBS,ffmpeg等程序可以通过对应的设置和参数对视频的GoP进行设置

那么引出了一个问题:GoP到底应该设置多大?那么GoP的大小到底有什么影响呢?

GoP设置比较大时:

好处:由于B帧和P帧的字节大小会比I帧小很多,所以GoP越长,所包含的B帧和P帧越多,相应的压缩比也会更高,或者说同样的码率下,视频会更清晰一些。

坏处:对于视频直播来说,播放器连接到服务器的时间是不固定的当播放器在GoP中间连接服务器,并获取了中间的B帧和P帧,这时播放器是无法对这些帧进行解码的,需要进行丢弃。所以会导致客户端的首屏播放时间变长(客户端需要等待一段时间才能看到图像)。

  2.  如果 GoP设置比较小时:

好处:由于GoP设置小可以降低I帧间隔时间,对于直播来说可以实现秒开的功能

坏处:由于GoP时间比较短,会导致I帧的比例增高,压缩比降低。同样码率情况下视频的质量会有所下降。
 
三 .为什么我的HLS视频加载会慢?

HLS (HTTP Live Streaming),Apple的动态码率自适应技术。主要用于PC和Apple终端的音视频服务。HLS格式的视频分为两个部分的。首先,HLS会根据指定的切片时间和实际的GoP大小对视频进行切割,并生成.ts文件。其次,HLS会生成一个.m3u8文件来保存这些ts文件的索引。
 
HLS协议可以用来做点播,也可以用来做直播。HLS直播是对直播流实时进行格式转换,并切片出.ts文件,同时更新.m3u8文件。客户端通过间歇获取新的.m3u8文件来获取新的.ts文件的索引。HLS点播是通过预先转码好的视频进行切片,并生成一个完整的.m3u8文件,客户端通过获取.m3u8文件来得到视频的时长和各个.ts切片文件的索引。

对于HLS格式的直播来说,.m3u8文件会在生成完一个.ts文件之后才生成。所以对于HLS直播来说,刚开始推流时,到第一个.ts文件生成完毕之前是无法打开的。同理,HLS的延迟也是跟.ts文件切片时间相关的。也就是说HLS的ts文件切片时间为1秒的话,HLS直播的延迟最小为1秒。

当然对于播放端来讲,下载.m3u8文件,然后下载第一个.ts文件也是需要花费一点时间的,那么这个时间也会加在延迟中

对于.ts文件的切割来讲,并不是告诉直播服务器指定1秒切一个.ts文件他就能保证1秒切一个.ts文件的。.ts文件的切割还是要根据直播视频的实际GoP大小来进行切割的。之前已经讲过,任何一个视频流在播放端需要能获取到完整的GoP才能播放,所以一个.ts文件所实际包含的时间是GoP的整数倍

例如:当视频的GoP设置为1秒,.ts切片时间为2秒时,实际的.ts文件切片所包含的视频为2秒。当视频的GoP设置为5秒,.ts切片时间为2妙时,实际的.ts文件切片所包含的视频为5秒。

从上面两个例子不难发现,视频流的实际GoP对HLS切片的时间影响非常大。如果视频流的GoP大小设置不合适的话,那么HLS的切片时间就会变长,同时也会增加HLS的延迟。这个特性对于HLS直播来讲简直就是延迟杀手。如果推流上来的GoP为10秒的话,不要说切出来一个.ts文件就要10秒,同时下载一个.ts文件所花费的时间也会大大增加

另外如果是HLS点播的话,流的GoP设置过大也会影响点播视频的(首屏)加载时间。一般的一个720P的视频,如果切片时间为2秒的话,单个.ts文件也就是在百K字节上下。对于现有的网速来讲,下载这么一个.ts文件很快。但如果源视频的GoP很大,会导致第一个.ts文件所包含的视频时常变长(比如10秒),同时导致.ts文件的大小膨胀到接近1M字节上下。想想看,如果第一个.ts文件是1M字节的话,播放器下载这个.ts文件的时间会是多久。
 
四.为什么我的RTMP直播首屏渲染速度很慢?

RTMP是Real Time Messaging Protocol(实时消息传输协议)的首字母缩写。该协议基于TCP,是一个协议族,包括RTMP基本协议及RTMPT/RTMPS/RTMPE等多种变种。RTMP是一种设计用来进行实时数据通信的网络协议,主要用来在Flash/AIR平台和支持RTMP协议的流媒体/交互服务器之间进行音视频和数据通信

对于RTMP协议的直播视频来说,它并不像HLS协议需要切.ts文件,它只是把视频流实时地进行转发即可。RTMP协议本身也会抽象出一个Packet的概念来封装H264编码中的帧,也就是一个Packet会包含1到多个帧,播放器以Packet为单位来进行解码。那么RTMP的问题在于客户端连接的时间点是否合适。

例如一个RTMP直播流的GoP设置为2秒,如果客户端接入时间刚好是第4秒,那么客户端会获取一个包含I帧的Packet,由于I帧是自描述的,所以客户端可以直接解码出该帧的画面并显示出来。但是当客户端的接入之间为第5秒,那么他会获得一个包含B帧或者P帧的Packet,由于客户端拿到的数据是一个不完整的GoP,所以客户端只好抛弃当前获取的Packet中视频的数据,而且只有当获取到包含下一个GoP的I帧的Packet时才能解码出图像。因此客户端会等待1秒才能播放出画面。

由此我们可以得出一个结论:GoP的大小会影响RTMP播放端的首帧加载时间。也就是说首帧加载时间最久为一个GoP的时间。当然,如何客户端运气够好的话,可以瞬间播放

为了优化首帧加载时间,我们可以在流媒体服务器端增加一个缓存,把上一个GoP缓存在内存中。如果客户端接入的话,我们首先放出来的是上一个GoP。这样客户端接到的数据永远是一I帧开头的数据

不过这种方案对于延迟要求比较高的场景下就不适合。毕竟GoP的缓存会增加一个延迟,具体延迟的时间也是跟GoP大小相关的。如果要实时性,那么GoP缓存并不能很好的解决问题,只能通过减少关键帧间隔的方式来进行调优了。

五.结论

在视频直播和点播盛行的年代,对于GoP大小的取舍还是需要看具体应用场景。对于直播来讲,对延迟要求敏感的应用来说,1~2秒的GoP大小还是比较合适的,至于GoP缓存来讲,还是不用为好。如果是对延迟要求不敏感,对首屏播放时间很敏感的应用,GoP还是1~2秒最为合适,GoP缓存应该是必备的。另外直播使用HLS的话,延迟是绝对PK不过RTMP的

对于点播的应用来说,视频加载速度是个硬指标,如果不是HLS格式的话,GoP大小适当选大一点可以降低视频文件大小,提高视频打开速度。HLS格式的话,还是推荐在2秒左右,否则很影响视频打开速度的。

其实视频直播技术的挑战很多,这次分享的只是其中一小部分,也是迅达云SpeedyCloud研发团队的经验总结,希望能够和大家多交流,一起为技术社区发展做些有益的事情。

六.Q&A

问题1:求推荐视频直播的知识资源,关于rmtp、h264编码的更多知识。大量视频文件存储服务器技术方案有哪些?
这方面的内容,可以通过翻阅wikipedia,Google来获取想要的知识。另外看一些开源项目的文档也会有所帮助。比如Nginx-RTMP-Module,Simple-rtmp-server,ffmpeg
 
问题2:视频直播这块有没有开源项目可以来练手的?  
上面说到了Nginx-rtmp,SRS,FFMPEG
 
问题3:nginx 的rtmp模块,可以配置gop缓存时间吗?
nginx-rtmp是没有GoP Cache的。Simple-RTMP-Server是有的。
 
问题4:求现在创业公司如何快速搭建自己的直播平台,是自研还是使用第三方平台,有哪些第三方平台可以推荐?
搭建直播平台的话,涉及的东西会很多,一般都是自研一部分,外包一部分
 
问题5:老师说到B侦和P侦需要参考侦才能解码,但在GoP的那张图中没有看到参考侦呀?
最前面和最后的两个橘黄色的是I帧。另外参考不一定是I帧,前后的B帧和P帧都可以做参考
 
问题6:ffmepg里,哪个选项是配置x264的 gop的?
-g参数可以设置gop长度,单位是帧。
 
问题7:就rtmpserver来说,哪些server使用者更多些?
这个看应用场景了,如果是自己用,Nginx-rtmp比较容易一些,如果是做CDN的话,simple-rtmp-server是个比较好的选择
# main config for srs. # @see full.conf for detail config. listen 1936; max_connections 1000; #srs_log_tank file; #srs_log_file ./objs/srs.log; daemon on; #srs_log_tank console; http_api { enabled on; listen 1985; } http_server { enabled on; listen 8080; dir ./objs/nginx/html; } rtc_server { enabled on; listen 8000; # UDP port # @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#config-candidate candidate 131.43.231.156; } vhost __defaultVhost__ { #转码配置 1080p -- 720p transcode { enabled on; ffmpeg /usr/bin/ffmpeg; engine ff { enabled on; vfilter { #缩放滤镜 调整分辨率 vf scale=1280:-1; } vcodec libx264; vbitrate 1500; vfps 30; vwidth 1280; vheight 720; vthreads 4; vprofile main; vpreset medium; vparams { #关键帧间隔 影响HLS切片 x264opts force_keyframe=expr:get(n,n_forced*50); } acodec aac; abitrate 128; asample_rate 44100; achannels 2; aparams { } output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; } } #HLS切片生成配置 hls { enabled on; hls_fragment 10; #切片时长(秒) hls_window 60; #保留切片总时长(秒) hls_path ./objs/nginx/html/hls; #切存储路径 hls_m3u8_file [app]/[stream].m3u8; hls_ts_file [app]/[stream]-[seq].ts; hls_cleanup on; #自动清理旧切片 } http_remux { enabled on; mount [vhost]/[app]/[stream].flv; } rtc { enabled on; # @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#rtmp-to-rtc rtmp_to_rtc on; # @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#rtc-to-rtmp rtc_to_rtmp on; } tcp_nodelay on; min_latency on; play { gop_cache off; queue_length 10; mw_latency 100; } publish { mr off; } } 这是我的srs服务器配置,但是直播延迟非常大,如何优化?
03-13
<think>嗯,用户提供的SRS配置存在高延迟问题,需要分析各个模块的配置。首先,延迟可能来自多个方面,比如转码、HLS切片、TCP设置以及播放参数。 看转码部分,用户使用了FFmpeg引擎,输出分辨率调整为1280x720,码率1500kbps,帧率30fps。这里要注意关键帧间隔的设置,x264opts中的force_keyframe被设置为每50帧强制一个关键帧。关键帧间隔过大会导致HLS切片无法在合适的时间切割,增加延迟。因为HLS通常依赖关键帧来切片,如果关键帧间隔是50帧,按30fps算的话,每个关键帧间隔约1.67秒,而HLS切片设置为10秒,这样每个切片可能需要等待多个关键帧,导致切片生成延迟。可能需要调整关键帧间隔,使其与HLS切片时长对齐,比如每10秒一个关键帧,即GOP大小设为300帧(30fps×10秒)。 接下来是HLS配置,hls_fragment设为10秒,hls_window是60秒,这会保留6个切片。但HLS的默认播放策略通常会等待至少3个切片后才开始播放,这样初始延迟就有30秒。可以考虑减少hls_fragment到2-3秒,并调整hls_window为6秒,这样能减少初始延迟,但会增加服务器负担。不过用户提到的是直播延迟大,可能需要权衡切片时长延迟。 在播放配置中,gop_cache被关闭,这会导致播放器不能使用GOP缓存,每次都需要等待完整的关键帧,可能增加延迟。开启gop_cache可以让播放器更快开始播放。另外,min_latency设置为on,这应该是有助于降低延迟的,但需要确认其他相关参数,如TCP_NODELAY播放队列长度。 RTC部分配置了rtmp_to_rtcrtc_to_rtmp,这可能涉及到WebRTC的低延迟传输。如果用户同时使用HLSWebRTC,那么HLS的延迟可能仍然存在。需要确认客户端使用的是哪种协议,如果是WebRTC应该延迟较低,而HLS则可能有较高延迟。如果用户主要使用HLS,可能需要优化HLS参数,或者考虑使用低延迟的协议如WebRTC或HTTP-FLV。 HTTP remux启用了FLV,这通常比HLS延迟低,因为FLV是基于长连接的流式传输。用户应检查客户端是否优先使用FLV而不是HLS,以降低延迟。 另外,检查转码输出是否增加了处理时间。FFmpeg转码可能会有一定的处理延迟,尤其是在使用较高分辨率码率时。可以尝试降低转码的复杂度,比如使用更快的x264预设(preset设为veryfast),减少vthreads的数量,或者调整分辨率码率。 总结可能的优化点:调整关键帧间隔与HLS切片一致,减少HLS切片时长,开启GOP缓存,优先使用低延迟协议如FLV或WebRTC,优化转码参数,检查网络候选地址是否正确,以及确保TCP_NODELAY生效。</think>以下是对SRS直播高延迟问题的优化方案,分模块逐步调整: $$关键帧对齐优化$$ 1. 修改转码引擎的关键帧间隔(与HLS切片对齐): ```conf x264opts force_keyframe=expr:gte(n,n_forced*$$(30 \times 10)$$); # 30fps × 10秒 ``` $$HLS低延迟配置$$ 2. 调整HLS参数组合: ```conf hls { enabled on; hls_fragment 3; # 切片从10秒→3秒 hls_window 30; # 保留约10个切片 hls_keys on; # 启用HLS加密切片 hls_key_file ./objs/nginx/html/keys/secret.key; hls_key_url https://yourdomain.com/keys/; hls_key_interval 3; # 每个切片包含完整GOP } ``` $$播放参数调优$$ 3. 调整播放缓存策略: ```conf play { gop_cache on; # 开启GOP缓存 queue_length 3; # 从10→3减少缓冲包数 mw_latency 50; # 最大等待时间100→50ms } ``` $$协议选择建议$$ 4. 优先使用低延迟协议: - 启用HTTP-FLV(已配置):延迟约1-3秒 - 禁用HLS(如允许):改为`enabled off` - 或保留HLS但客户端优先使用FLV $$转码加速参数$$ 5. 优化x264编码参数: ```conf engine ff { vpreset veryfast; # medium→veryfast vthreads 8; # 根据CPU核数调整 vprofile baseline; # 简化解码复杂度 } ``` $$RTC增强配置$$ 6. WebRTC补充配置: ```conf rtc_server { candidate 131.43.231.156:8000; # 明确端口 # 新增带宽配置 bandwidth { pub 2000kbps; sub 2500kbps; } } ``` $$系统级调优$$ 7. 内核参数调整(需root): ```bash # 增加UDP缓冲区 sysctl -w net.core.rmem_max=26214400 sysctl -w net.core.wmem_max=26214400 ``` 验证步骤: 1. 使用`http://yourdomain.com:8080/live/livestream.flv`测试FLV延迟 2. 通过`WebRTC播放器`测试实时性 3. 监控转码耗时:`ffmpeg -benchmark`输出处理时间 4. 检查网络延迟:`tcpdump -i eth0 udp port 8000` 典型优化效果: - HTTP-FLV延迟:$$500ms \sim 2s$$ - WebRTC延迟:$$200ms \sim 800ms$$ - HLS延迟:$$切片时长 \times 1.5$$(原10秒→优化后约5秒) 注意事项: 1. 公网IP`131.43.231.156`需确保UDP端口8000开放 2. 关键帧间隔必须≥切片时长 3. 4核以上服务器建议保持`vthreads=4` 4. 高并发场景需同步调整`max_connections`参数
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值