- 1. FFMPEG录像
- 2. FFMPEG解码
- 3. 播放YUV
- 4. 转码
- 5. 编码
- 6. 推流
- 7. 处理Extra
- 8. 直播方案
- 9. 转码
- 10. 保存图片
- 11. 合并MP4文件
- 12. 播放
1. FFMPEG录像
1.1 h264 over rtsp-保存NAL流
ffmpeg -rtsp_transport tcp -i "rtsp://192.168.68.2/" -c:v copy -f h264 foo.264
注意在FFMPEG 3.3.2上测试发现,如果-rtsp_transport tcp
放到 -i "rtsp://192.168.68.2/"
之后,会依然使用UDP
传输RTP
,而不是TCP
。
按照时间间隔录像:
ffmpeg -rtsp_transport tcp -i rtsp://user:password@192.168.68.2 -codec copy -map 0 -f segment -segment_time 10 -segment_format mp4 "device-19-%03d.mp4"
1.2 h264 over rtsp-保存为MP4封装
ffmpeg -rtsp_transport tcp -i "rtsp://user:password@192.168.68.64" -c:v copy -f mp4 foo.mp4
1.3 mpeg4 over rtsp-保存为MP4封装
和上面一样
1.4 h264文件封装为MP4文件
ffmpeg -i "foo.h264" -c:v copy -f mp4 foo.mp4
1.5 解封装MP4文件为h264文件
ffmpeg -i foo.mp4 -c:v copy -f h264 foo.h264
1.6 10次循环录像,每个录像文件10分钟
record_rtsp.bat
SET hour=%time:~0,2%
IF "%hour:~0,1%"==" " (
SET hour_prefix=0
) ELSE (
SET hour_prefix=%hour:~0,1%
)
SET hour=%hour_prefix%%hour:~1,1%
SET timestamp=%date:~0,4%%date:~5,2%%date:~8,2%%hour%%time:~3,2%%time:~6,2%
for /l %%x in (1, 1, 10) do (
ffmpeg.exe -rtsp_transport tcp -i "rtsp://192.168.68.2" -acodec copy -vcodec copy -ss 00:00:00 -t 00:10:00 record_%timestamp%_%%x.h264
)
1.7. MP4录像
MP4格式,每10秒一个文件,每个关键帧切片
ffmpeg -rtsp_transport tcp -stimeout 2000000 -i rtsp://user:password@192.168.68.10 -c copy -map 0 -f segment -strftime 1 -strftime_mkdir 1 -segment_time 10 -segment_format mp4 -segment_format_options "movflags=frag_keyframe+empty_moov" "%Y%m%d_%H%M%S.mp4"
如果采用UDP协议来传输媒体,可修改上面TCP为UDP。
2. FFMPEG解码
2.1 ffplay-列出解码器
ffplay -decoders
2.2 ffplay-列出cuvid相关解码器
ffplay -decoders | grep cuvid
输出
1
2
3
4
5
6
7
8
9
V..... h264_cuvid Nvidia CUVID H264 decoder (codec h264)
V..... hevc_cuvid Nvidia CUVID HEVC decoder (codec hevc)
V..... mjpeg_cuvid Nvidia CUVID MJPEG decoder (codec mjpeg)
V..... mpeg1_cuvid Nvidia CUVID MPEG1VIDEO decoder (codec mpeg1video)
V..... mpeg2_cuvid Nvidia CUVID MPEG2VIDEO decoder (codec mpeg2video)
V..... mpeg4_cuvid Nvidia CUVID MPEG4 decoder (codec mpeg4)
V..... vc1_cuvid Nvidia CUVID VC1 decoder (codec vc1)
V..... vp8_cuvid Nvidia CUVID VP8 decoder (codec vp8)
V..... vp9_cuvid Nvidia CUVID VP9 decoder (codec vp9)
2.3. ffmpeg-列出nvidia相关编码器
ffmpeg -encoders | grep nvenc
输出
1
2
3
4
5
V..... h264_nvenc NVIDIA NVENC H.264 encoder (codec h264)
V..... nvenc NVIDIA NVENC H.264 encoder (codec h264)
V..... nvenc_h264 NVIDIA NVENC H.264 encoder (codec h264)
V..... nvenc_hevc NVIDIA NVENC hevc encoder (codec hevc)
V..... hevc_nvenc NVIDIA NVENC hevc encoder (codec hevc)
2.4 ffplay 3.3.2-Nvidia显卡解码h264视频
ffplay -vcodec h264_cuvid -rtsp_transport tcp -i "rtsp://user:password@192.168.68.2" -x 1200 -y 600
指定显卡0来转码测试显卡性能:
ffmpeg -gpu 0 -vcodec hevc_cuvid -rtsp_transport tcp -i "rtsp://user:password@192.168.68.2" -f null null
2.5 ffplay低延迟播放RTSP
ffplay -fflags nobuffer -rtsp_transport tcp -i "rtsp://user:password@192.168.68.2" -x 1200 -y 600
3. 播放YUV
3.1 播放YUV文件
I420格式:
ffplay -f rawvideo -video_size 1920x1080 foo.yuv
yuv420格式:
ffplay -f rawvideo -video_size 5760x1080 -pix_fmt yuv420p foo.yuv
NV12格式:
ffplay -f rawvideo -pix_fmt nv12 -video_size 5760*1080 foo.yuv -x 1500 -y 600
3.2 缩放YUV
ffmpeg -s:v 1920x1080 -r 25 -i HeavyHand_1080p.yuv -vf scale=5760:1080 -c:v rawvideo -pix_fmt yuv420p foo_output.yuv
4. 转码
h265转码为YUV
把foo.h265转为foo.yuv
ffmpeg -i foo.h265 foo.yuv
播放YUV
ffplay -f rawvideo -video_size 5760x4320 foo.yuv -x 800 -y 600
JPG转码为YUV i420
ffmpeg -i input.jpg -s 1920x1080 -pix_fmt yuv420p output.yuv
YUV i420 编码为JPG
ffmpeg -s 1920x1080 -pix_fmt yuv420p -i input.yuv output.jpg
转码MP4-降低码率
通过OBS做视频,用剪映添加字幕后,发现3分钟视频变得很大,下面用ffmpeg降视频码率为300Kbps,并保持音频不变:
ffmpeg -i source.mp4 -acodec copy -b:v 0.3M dst.mp4
降延时,减少GOP长度
- GPU转码,用nvidia显卡
ffmpeg -i in.h264 -an -vcodec h264_nvenc -g 25 -b:v 2M -f h264 out.h264
- CPU转码,libx264
ffmpeg -i in.h264 -an -vcodec libx264 -g 25 -b:v 2M -f h264 out.h264
视频截断
把视频的第60秒~70秒,截取保存为out.mp4
ffmpeg -ss 00:01:00.000 -t 10 -i in.mp4 -codec copy out.mp4
制作gif表情符
ffmpeg -ss 00:00:02.2 -t 1.3 -i hutiehua_twist.mp4 -an -vf "scale=320:-1:flags=lanczos" hutiehua.gif
5. 编码
ffmpeg -s 5760x1080 -pix_fmt yuv420p -i foo.yuv -r 25 foo.h264
6. 推流
- 推送h264文件到TCP端口、并关闭音频:
ffmpeg -re -i "d://a.h264" -c:v copy -an -f h264 tcp://127.0.0.1:14011
- 推送h265文件到TCP端口:
ffmpeg -re -stream_loop -1 -i "d://main_20180927_093305.h265" -c:v copy -f hevc tcp://127.0.0.1:14011
6.3. RTSP->FFMPEG->TS
- 接收RTSP,转为MPEG TS:
ffmpeg -fflags nobuffer -rtsp_transport tcp -i "rtsp://user:password@192.168.68.2" -c copy -f mpegts tcp://127.0.0.1:9000
- 播放:
ffplay -i "tcp://127.0.0.1:9000?listen=1" -f mpegts -x 1920 -y 1080
6.4. RTSP->FFMPEG->RTP
- 接收RTSP,转为RTP:
ffmpeg -rtsp_transport tcp -i "rtsp://user:password@192.168.68.2" -an -c copy -f rtp rtp://192.168.68.2:14011 -sdp_file live.sdp
- 播放:
ffplay -protocol_whitelist "file,rtp,udp" -i live.sdp -x 1920 -y 1080
6.5. RTSP->FFMPEG->HLS,HLS直播
ffmpeg -rtsp_transport tcp -i rtsp://192.168.68.2 -codec copy -f hls -hls_time 5 -hls_list_size 10 -hls_flags delete_segments live.m3u8
实现如下功能:
- rtsp转为hls,codec不变
- 每个ts文件5秒
- m3u8中提供10个ts的引用
- 当ts文件过期于整个m3u8播放列表的时长时,删除该ts文件
7. 处理Extra
7.1 Extra Data
通常是指h264和h265的VPS/SPS/PPS
等。
如果想要去掉Extra和Audio数据如下操作:
ffmpeg -i 5760x4320_xy.h265 -vbsf remove_extra -vcodec copy -an 5760x4320_xy_no_extra.h265
-vbsf
表示bitstream filters
,ffmpeg -bsfs
可查看支持的过滤器列表:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
aac_adtstoasc
chomp
dump_extra
dca_core
extract_extradata
h264_mp4toannexb
hevc_mp4toannexb
imxdump
mjpeg2jpeg
mjpegadump
mp3decomp
mpeg4_unpack_bframes
mov2textsub
noise
remove_extra
text2movsub
vp9_superframe
7.2 把已有的Extra Data
,加到每个关键帧
ffmpeg -i 5760x4320_xy.h265 -vbsf dump_extra=freq=keyframe -vcodec copy -an 5760x4320_xy_no_extra.h265
7.3 去掉每个GOP都带的VPS/SPS/PPS
- 从文件中提取
VPS/SPS/PPS
到独立文件:dd if=5760x4320_xy.h265 of=5760x4320_extra.h265 count=1 bs=95
- 从文件中移除所有
VPS/SPS/PPS
到独立文件:ffmpeg -i 5760x4320_xy.h265 -vbsf remove_extra -vcodec copy -an 5760x4320_xy_no_extra.h265
- 合并
5760x4320_extra.h265
和5760x4320_xy_no_extra.h265
。
7.4. 打印每一帧信息
ffmpeg -i <inputfile> -c:v copy -bsf:v trace_headers -f null -
- 看每帧类型:
ffprobe -show_frames -i <inputfile> | grep pict_type
- 看每帧完整信息:
ffprobe -show_frames -i <inputfile>
输出示例[FRAME] media_type=video stream_index=0 key_frame=0 pts=10 pts_time=0.400000 pkt_dts=10 pkt_dts_time=0.400000 best_effort_timestamp=10 best_effort_timestamp_time=0.400000 pkt_duration=1 pkt_duration_time=0.040000 pkt_pos=400100 pkt_size=12433 width=1280 height=720 pix_fmt=yuv420p sample_aspect_ratio=1:1 pict_type=P coded_picture_number=10 display_picture_number=0 interlaced_frame=0 top_field_first=0 repeat_pict=0 color_range=unknown color_space=unknown color_primaries=unknown color_transfer=unknown chroma_location=left [/FRAME] [FRAME] media_type=audio stream_index=1 key_frame=1 pts=3200 pts_time=0.400000 pkt_dts=3200 pkt_dts_time=0.400000 best_effort_timestamp=3200 best_effort_timestamp_time=0.400000 pkt_duration=320 pkt_duration_time=0.040000 pkt_pos=110174 pkt_size=320 sample_fmt=s16 nb_samples=320 channels=1 channel_layout=unknown [/FRAME]
7.5. h264加入SEI
ffmpeg -i original.mp4 -c copy -bsf:v h264_metadata=sei_user_data='086f3693-b7b3-4f2c-9653-21492feee5b8+hello' file_with_h264_metadata.mp4
8. 直播方案
8.1 rtsp to m3u8/ts,支持文件名和目录的时间戳
ffmpeg -rtsp_transport tcp -i rtsp://user:password@192.168.68.2 -hls_time 5 -hls_list_size 3 -strftime 1 -strftime_mkdir 1 -hls_segment_filename 'device_xxx/%Y%m%d/device_19-%Y%m%d_%H%M%S.ts' -f hls device_xxx/out.m3u8
8.2 rtsp to mp4
ffmpeg -rtsp_transport tcp -i rtsp://user:password@192.168.68.2 -codec copy -map 0 -f segment -segment_time 10 -segment_format mp4 "device-19-%03d.mp4"
遗留问题
-f segment
形式时无法利用-fs 102400
来指定文件长度。-f hls
则既可以按照时间,也可以按照文件长度,考虑中。
9. 转码
把a.h264文件转码为分辨率640x360的sub.h264文件。
ffmpeg -i a.h264 -vcodec libx264 -s 640x360 -preset ultrafast sub.h264
10. 保存图片
JPG
ffmpeg -rtsp_transport tcp -i rtsp://user:password@192.168.68.2 -f image2 -vframes 1 -y 250.jpg
-y表示强制覆盖已存在的250.jpg。
10个JPG
ffmpeg -rtsp_transport tcp -i rtsp://user:password@192.168.68.2 -f image2 -vframes 10 -y 250_%d.jpg
BMP
修改上面命令中后缀为.bmp即可。
YUV
ffmpeg -rtsp_transport tcp -i rtsp://user:password@192.168.68.2 -f image2 -vframes 1 -y 250.y
除250.y之外,还会产生250.u和250.v。
11. 合并MP4文件
ffmpeg -i 1.mp4 -i 2.mp4 -filter_complex "[0:v:0][0:a:0][1:v:0][1:a:0]concat=n=2:v=1:a=1[outv][outa]" -map "[outv]" -map "[outa]" output.mp4
其他方式如ffmpeg -f concat -safe 0 -i mylist.txt -c copy output.mp4
等要么只有第一个文件,要么音频混淆了。
12. 播放
12.1. 4倍速
ffplay -f h264 file.264 -vf "setpts=0.25*N/FRAME_RATE/TB"
12.2. 1/4倍速
ffplay -f h264 file.264 -vf "setpts=4*N/FRAME_RATE/TB"