我买了一个便宜的中国网络摄像头(GWIPC-26xxx/Yoosee)。我想用ffmpeg记录它的流。
在FFMPEG我设法使它工作只有使用RTSP/UDP传输协议,如下面所示。它也可以完美地播放VLC。
ffmpeg -rtsp_transport udp -i rtsp://admin:pass@192.168.0.103:554/onvif1 streamfile.mkv
pass
为android相机app客户端定义的密码。
但是我非常喜欢RTSP/TCP传输因为使用UDP,图像经常损坏。图像似乎被涂抹和撕裂。因此,我测试了几乎所有内容,甚至使用最新的存储库从源代码编译FFMPEG
。但是无论android还是windows, ffmpeg都无法正常工作。如果使用-rtsp_transport tcp
,我总是最终接收到:
[rtsp @ 0xxxxxxx] Nonmatching transport in server reply
最终发现openRTSP使用了VLC使用的相同库。有了它,我设法使它连接使用RTSP/TCP (从源代码编译后)。
openRTSP -n -D 1 -c -B 10000000 -b 10000000 -q -Q -F cam_file
-d 60 -P 30 -t -u admin pass rtsp://192.168.0.103:554/onvif1
更多关于openRTSP
参数的详细信息在这里。
看ffmpeg/libavformat/rtsp.c
的源代码它接缝ffmpeg有一些问题识别它?
...
if (reply->transports[0].lower_transport != lower_transport) {
av_log(s, AV_LOG_ERROR, "Nonmatching transport in server replyn");
err = AVERROR_INVALIDDATA;
goto fail;
}
...
名言智慧
IP摄像机质量参差不齐,在我的经验中有些行为不稳定。处理它们的RTSP流需要一定的容错性。
这似乎是中低端CCTV行业对标准忽快忽慢的副产品,RTSP和ONVIF为两个最常被滥用的.幸运的是,您通常可以解决这些问题。除非你的IP摄像机和控制器都设计得很好,否则只使用ONVIF进行一次性发现和设置管理。
FFMPEG在RTSP设置中不是很耐受
挣扎之后,我开始比较RTSP/SETUPopenRTSP
和ffmpeg
之间的消息。默认情况下,openRTSP
已经输出了大量详细的诊断信息。
openRTSP
openRTSP
发送命令OPTIONS
、DESCRIBE
和SETUP
。SETUP消息为:
Sending request: SETUP rtsp://192.168.0.103:554/onvif1/track2 RTSP/1.0
CSeq: 6
Authorization: Digest username="admin", realm="HIipCamera", nonce="ddd21dbd0620b6fb4b1f9bcbb06340a0", uri="rtsp://192.168.0.103:554/onvif1", response="91d9c611aa004eeb1390b3fbb9373648"
User-Agent: ./openRTSP (LIVE555 Streaming Media v2021.02.11)
Transport: RTP/AVP/TCP;unicast;interleaved=2-3
Session: 3a4d2e6d
相机响应:
Received a complete SETUP response:
RTSP/1.0 200 OK
CSeq: 6
Transport: RTP/AVP;unicast;destination=192.168.0.100;source=192.168.0.103;interleaved=2-3
Session: 3a4d2e6d;timeout=60
FFMPEG>对于FFMPEG
,您必须使用-v 9 and -loglevel 99
参数来查看RTSP消息。它只发送了一个DESCRIBE
请求:
DESCRIBE rtsp://192.168.0.103:554/onvif1 RTSP/1.0
Accept: application/sdp
CSeq: 2
User-Agent: Lavf58.67.100
相机响应:
Transport: RTP/AVP;unicast;destination=192.168.0.100;source=192.168.0.103;interleaved=0-1
Session: 37287775;timeout=60
RTSP滥用与FFMPEG破解-解决方案
比较消息,很明显相机可以连接使用RTSP/AVP/TCP交错TCP。但是我们可以从相机的回答中看到,在'Transport:'行它不包括'TCP'在"RTP/avon">应要求。如:
Transport: RTP/AVP/('TCP' missing here);....
我分析了和ffmpeg/libavformat/rtsp.c
上的代码,发现了直观的以下调用顺序:ff_rtsp_connect
,ff_rtsp_make_setup_request
,ff_rtsp_send_cmd
,ff_rtsp_read_reply
和ff_rtsp_parse_line
。在最后一个中,我找到了rtsp_parse_transport
和以下代码:
if (!av_strcasecmp(lower_transport, "TCP"))
th->lower_transport = RTSP_LOWER_TRANSPORT_TCP;
else
th->lower_transport = RTSP_LOWER_TRANSPORT_UDP;
lower_transport
是'RTP/AVP;'
后解析的文本,在我的情况下是""
空字符串,因为相机服务器没有包含它。
我在代码中插入了|| !av_strcasecmp(lower_transport, "")
。当lower_transport
被提交时,假设传输是RTSP_LOWER_TRANSPORT_TCP
。像风箱:
if (!av_strcasecmp(lower_transport, "TCP") || !av_strcasecmp(lower_transport, ""))
th->lower_transport = RTSP_LOWER_TRANSPORT_TCP;
else
th->lower_transport = RTSP_LOWER_TRANSPORT_UDP;
这个ffmpeg的小补丁(git)可以在这里获得。在ffmpeg git repo上使用git am < RTSP_lower_transport_TCP.patch
重新编译后:FFMPEG工作完美!
I黑客FFMPEG使它容忍RTSP滥用相机服务器正在做的。因为我的版本的FFMPEG将只运行在我未使用的安卓电视(作为cctv/nvr摄像机服务器),这不会产生任何其他问题。
一个更好的解决方案是FFMPEG(票证),也考虑在rtsp服务器应答中缺少较低传输的情况。然后与客户端发送的请求进行比较,以定义是否提交了较低的传输。并试着与它连接。
建议如果你到达这里,你的ip摄像头可能会被RTSP滥用了。我建议您先尝试使用openRTSP
,看看它是否能够成功连接。如果是,那么尝试调试它的RTSP/setup消息。如果您修改(自担风险)ffmpeg/libavformat/rtsp.c
代码,则可能存在一些自定义或黑客解决方案。或者你可以/应该使用live555库,VLC或mplayer。