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长度

  1. GPU转码,用nvidia显卡

ffmpeg -i in.h264 -an -vcodec h264_nvenc -g 25 -b:v 2M -f h264 out.h264

  1. 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. 推流

  1. 推送h264文件到TCP端口、并关闭音频:ffmpeg -re -i "d://a.h264" -c:v copy -an -f h264 tcp://127.0.0.1:14011
  2. 推送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

  1. 接收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
  2. 播放:ffplay -i "tcp://127.0.0.1:9000?listen=1" -f mpegts -x 1920 -y 1080

6.4. RTSP->FFMPEG->RTP

  1. 接收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
  2. 播放: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

实现如下功能:

  1. rtsp转为hls,codec不变
  2. 每个ts文件5秒
  3. m3u8中提供10个ts的引用
  4. 当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 filtersffmpeg -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

  1. 从文件中提取VPS/SPS/PPS到独立文件:dd if=5760x4320_xy.h265 of=5760x4320_extra.h265 count=1 bs=95
  2. 从文件中移除所有VPS/SPS/PPS到独立文件:ffmpeg -i 5760x4320_xy.h265 -vbsf remove_extra -vcodec copy -an 5760x4320_xy_no_extra.h265
  3. 合并5760x4320_extra.h2655760x4320_xy_no_extra.h265

参考:ffmpeg-bitstream-filters

7.4. 打印每一帧信息

  1. ffmpeg -i <inputfile> -c:v copy -bsf:v trace_headers -f null -
  2. 看每帧类型:ffprobe -show_frames -i <inputfile> | grep pict_type
  3. 看每帧完整信息: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"

遗留问题

  1. -f segment形式时无法利用-fs 102400来指定文件长度。
  2. -f hls则既可以按照时间,也可以按照文件长度,考虑中。

9. 转码

a.h264文件转码为分辨率640x360sub.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"

参考

  1. setpts和asetpts