我使用ffmpeg从Cisco 3050 IP摄像机读取h264 RTSP流并将其重新编码为磁盘h264(我有理由不仅使用-codec:copy
)。< / p>
ffmpeg版本如下:
ffmpeg version 3.2.6 Copyright (c) 2000-2017 the FFmpeg developers
built with gcc 6.3.0 (Alpine 6.3.0)
我还尝试过使用ffmpeg 2.8.14-0ubuntu0.16.04.1以及从源代码构建的最新ffmpeg(我使用this提交)并看到与下面相同的行为。
我正在运行的命令是:
ffmpeg -rtsp_transport udp -i 'rtsp://<user>:<pw>@<ip>:554/StreamingSetting?version=1.0&action=getRTSPStream&ChannelID=1&ChannelName=Channel1' -r 10 -c:v h264 -crf 23 -x264-params keyint=60:min-keyint=60 -an -f ssegment -segment_time 60 -strftime 1 /output/%Y%m%d_%H%M%S.ts -abort_on empty_output
我以相当稳定的速度获得各种错误,至少每秒一次。这是一个样本:
[rtsp @ 0x7f268c5e9220] max delay reached. need to consume packet
[rtsp @ 0x7f268c5e9220] RTP: missed 40 packets
[h264 @ 0x55b1e115d400] left block unavailable for requested intra mode
[h264 @ 0x55b1e115d400] error while decoding MB 0 12, bytestream 114567
[h264 @ 0x55b1e115d400] concealing 3889 DC, 3889 AC, 3889 MV errors in I frame
最常见的一个是在解码MB x x,字节流x&#39;时出错。这对应于播放时视频文件中的严重损坏。
我在stackoverflow和其他地方看到很多对该错误消息的引用,但我还没有找到令人满意的解释或解决方法。它来自this line,它似乎对应于流末尾的缺失数据。 &#39;左边的区块不可用&#39;来自here,看起来也像缺少数据。
其他人建议使用-rtsp_transport tcp
代替1,2,3),在我的情况下,这只会给出略有不同的错误组合,并且仍会出现视频损坏:
[h264 @ 0x557923191b00] left block unavailable for requested intra4x4 mode -1
[h264 @ 0x557923191b00] error while decoding MB 0 28, bytestream 31068
[h264 @ 0x557923191b00] concealing 2609 DC, 2609 AC, 2609 MV errors in I frame
[rtsp @ 0x7f88e817b220] CSeq 5 expected, 0 received.
使用Wireshark我确认在UDP和TCP模式下,所有数据包都是从摄像头到PC(顺序RTP序列号没有丢失),这让我觉得数据在到达之后就丢失了FFMPEG。
在对Panasonic WV-SFV110相机运行相同命令时,我也会看到类似的行为,但整体错误较少。在Panasonic相机上从UDP切换到TCP可以减少但不能完全消除错误/损坏。
我也尝试过与VLC类似的命令并得到类似的错误(cvlc rtsp://<user>:<pw>@<ip>/MediaInput/h264 :sout='#transcode{vcodec=h264}:std{access=file, mux=ts, dst="output.ts"}
) - 可能是因为libav从ffmpeg分叉后代码没有多大分歧。
摄像头直接插入PC上的PoE端口,因此网络拥塞可能不是问题。鉴于PC有足够的CPU来保持对实时流的编码,在我看来,ffmpeg仍然存在从TCP流中丢弃数据的问题。
定性地说,有几个因素似乎使问题变得更糟:
-codec:copy
消除除ffmpeg启动时的所有错误除外)错误是什么意思?我能做些什么呢?
答案 0 :(得分:4)
查看初始错误消息:
[rtsp @ 0x7f268c5e9220] max delay reached. need to consume packet
[rtsp @ 0x7f268c5e9220] RTP: missed 40 packets
我猜你正在丢失UDP数据包。其余的H.264错误消息是由接收不完整的比特流引起的。 现在关键是要隔离问题。你的网络丢包了吗?或者您的服务器接收UDP(RTP)太慢或过载。
首先,我要检查操作系统的UDP缓冲区大小。 https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Web_Platform/5/html/Administration_And_Configuration_Guide/jgroups-perf-udpbuffer.html
如果增加UDP缓冲区大小没有帮助 - 使用ffmpeg和-codec:copy
来降低CPU负载。你还有错误吗?
由于您要重新编码,请考虑使用Intel Quicksync -vcodec h264_qsv
或其他一些硬件编码器来降低CPU负载。
问题不在于PC是否具有足够的CPU 。但更多关于识别处理管道中的瓶颈。您的H.264编码器(x264)可能会过度订阅CPU,从而导致瞬间峰值负载导致数据包丢失。尝试限制x264的线程数和/或将质量降低到快速&#39;或者&#39;更快&#39;。
答案 1 :(得分:1)
听起来像丢包是一个问题。较高的视频分辨率和较大的运动都会增加编码视频流的比特率,从而增加数据包丢失。根据您丢失的数据包,您将在帖子中指出的解码过程中看到不同的错误。
运行ffmpeg的较高系统负载也表示您的网卡可能正在丢弃数据包,例如ffmpeg在忙于转码视频时需要很长时间才能读取它们。
第一个问题是您的网络拓扑是什么?通过公共互联网进行流式传输比通过LAN进行流式传输要困难得多。网络中有哪种交换机/路由器?
接下来的问题,你的相机流媒体的比特率是多少?尝试减少这一点并检查结果。你的方法要系统化,即
我要做的下一件事是增加接收器缓冲区的大小。虽然我对ffmpeg并不熟悉,但看起来您可以通过recv_buffer_size
设置here。然后,您需要根据相机配置计算出足够大的尺寸来存储,例如一对(5?)秒的视频数据。在增加接收器缓冲区大小或更长时间没有伪像的情况下检查是否存在较少的伪像。
当然,如果您的处理器太慢而无法实时转码视频,您迟早会用完空间,在这种情况下,您可能需要转码为较低的分辨率/比特率或使用不太密集的编码器设置等,或在更快的机器上运行转码。
另外,请注意,调整接收器缓冲区大小不会补偿公共Internet上发生的数据包丢失,因此上述内容将有助于假设您在支持摄像机比特率的本地网络上进行流式传输。如果超出网络带宽,则可能会丢失数据包。在这种情况下,通过TCP流式传输可能有所帮助(至少在接收器缓冲区最终超出之前)。
如果以上内容无法帮助或完全解决问题,您可以尝试更多的事情:
总之,您有一个管道架构,您需要确定管道中发生丢失的位置:
camera -> network -> receiver buffer (OS) -> application (ffmpeg)