最近用ffmpeg 做hls 的切片 当用海康的摄像机做rtsp流输入:
ffmpeg 命令如下:ffmpeg -y -i "rtsp://220.178.65.131:554/hikvision://218.23.62.231:8000:0:1?username=admin&password=12345" -c:v copy -map 0:0 -flags -global_header -f segment -segment_list playlist.m3u8 -segment_time 10 -segment_format mpeg_ts -segment_list_type m3u8 segment%05d.ts
问题:切片内容不能时事输出,除非收到中断(ctrl+c)才会输出所有的切片文件 和 m3u8文件。
原因:海康摄像机rtsp 流 返回的sdp 中显示有音频流的(而实际上是没有的)。下面 是 海康返回的SDP
v=0
o=- 1109162014219182 0 IN IP4 0.0.0.0
s=HIK Media Server
i=HIK Media Server Session Description : standard
e=NONE
c=IN IP4 0.0.0.0
t=0 0
a=control:*
a=range:npt=0.0-
m=video 0 RTP/AVP 96
i=Video media
a=rtpmap:96 H264/90000
a=fmtp:96 profile-level-id=4D0014;packetization-mode=0
a=control:trackID=1
m=audio 0 RTP/AVP 98
i=Audio media
a=rtpmap:98 G7221/16000
a=control:trackID=2
a=Media_header:MEDIAINFO=494D4B48010100000400000121720110803E0000803E000000000000000000000000000000000000;
a=appversion:1.0
下面是探测结束后的到的输入 输出的matadata:
Input #0, rtsp, from 'rtsp://220.178.65.131:554/hikvision://218.23.62.231:8000:0:1?username=admin&password=12345':
Metadata:
title : HIK Media Server
comment : HIK Media Server Session Description : standard
Duration: N/A, start: 3.400000, bitrate: N/A
Stream #0:0: Video: h264 (Baseline), yuv420p, 352x288, 30 fps, 30 tbr, 90k tbn, 60 tbc
Stream #0:1: Audio: none, 16000 Hz, mono
[segment @ 0x1cdb640] Codec for stream 0 does not use global headers but container format requires global headers
Output #0, segment, to 'segment%05d.ts':
Metadata:
title : HIK Media Server
comment : HIK Media Server Session Description : standard
encoder : Lavf54.63.104
Stream #0:0: Video: h264, yuv420p, 352x288, q=2-31, 30 fps, 90k tbn, 30 tbc
Stream mapping:
Stream #0:0 -> #0:0 (copy)
Press [q] to stop, [?] for help
在解析海康摄像机返回的SDP时(libavformat/rtsp.c :ff_sdp_parse() 521行)将 AVFormatContext s 的nb_streams 设置成了2 。
但在输出输出时 因为有两路流 所以调用了 interleaved 相关的函数 如调用了av_interleaved_write_frame()->interleave_packet->()->ff_interleave_packet_per_dts() .而在ff_interleave_packet_per_dts()函数中 要比较是不是两路流的最后buffer都到了。而音频是没有的因此 就认为音频没有来,所以变量flush(代表是否输出)。就仍然为 0 。
解决方法:我认为解决方法有两个,一个就是在分析SDP时 ,核实真正的流,才增加 nb_stream 。比如有codecID
第二个是:在输出时不管如何将 flush 设置为1 。(我用了这种,这个可能有隐患,我还不清楚)。
本人对ffmpeg 代码刚开始读,好多都不太熟悉,欢迎各位指正。