ffmpeg基本功能使用

1. 任务描述:由给定图像序列合成 24fps 视频

方案一

直接对图像进行操作,适用于图像名比较规范且默认顺序即为所需顺序的情景

ffmpeg -f image2 -i ./images_crop_%d.png -pix_fmt yuv420p -vcodec libx264 -r 24 -y output.mp4

方案二

将图像顺序写入一个文件列表,让 ffmpeg 从列表读入并合成视频,适用于自定义图像顺序的情景

ffmpeg -f concat -safe 0 -i input.txt -pix_fmt yuv420p -vcodec libx264 -r 24 -y -an output.mp4

其中列表格式如下

file '/Users/cv/playground/data/cam_1_frame_00.png'
duration 0.5
file '/Users/cv/playground/data/cam_2_frame_01.png'
duration 0.5
……
input.txt

file 设置当前帧图像路径,使用绝对路径防止出错。

duration 设置当前帧与下一帧的时间间隔,单位是秒(s)。

可能出现的错误及解决方法

错误提示:如果图像的宽或高不是偶数,在转换过程中会出现下面的问题

[libx264 @ 0x7fec87003c00] height not divisible by 2 (2000x1125)
Error initializing output stream 0:0 -- Error while opening encoder for output stream #0:0 - maybe incorrect parameters such as bit_rate, rate, width or height
Conversion failed!
Error Occur

解决方案:在转换过程中对宽和高重新调整

ffmpeg -f concat -safe 0 -i input.txt -pix_fmt yuv420p -vcodec libx264 -r 24 -y -an -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" output.mp4

 

2. 任务描述:将视频拆分成图像序列

直接输入需要分解的视频名,并指定输出图像的格式即可

ffmpeg -i video.mpg image%d.jpg
ffmpeg -i scene2frame1.mov frame%d.png
ffmpeg -i src.mp4 -vframes 200 bmp_images/camera_01/%04d.bmp
ffmpeg -i src.mp4 -vf scale=1920:1080 -vframes 200 bmp_resize/camera_01/%04d.bmp

vframes 用于设置提取的帧数。

vf scale 用于设置提取帧之后输出的分辨率,可用于对提取帧进行 resize 处理。

 

3. 任务描述:将 YUV420P10LE 格式的图片/视频转换成 YUV420P 格式

先查看原图格式

cv:~ cv$ ffprobe -hide_banner -show_format cam-1-frame-1_yuv420ple.png 
Input #0, png_pipe, from 'cam-1-frame-1_yuv420ple.png':
  Duration: N/A, bitrate: N/A
    Stream #0:0: Video: png, rgb48be(pc), 3840x2160 [SAR 1:1 DAR 16:9], 25 tbr, 25 tbn, 25 tbc
[FORMAT]
filename=cam-1-frame-1_yuv420ple.png
nb_streams=1
nb_programs=0
format_name=png_pipe
format_long_name=piped png sequence
start_time=N/A
duration=N/A
size=35370650
bit_rate=N/A
probe_score=99
[/FORMAT]

然后使用 ffmpeg 转换格式

cv:~ cv$ ffmpeg -pix_fmt yuv420p10le -i cam-1-frame-1.png -pix_fmt yuv420p cam-1-frame-1_yuv420p.png

然后查看转换后的图像的格式

cv:~ cv$ ffprobe -hide_banner -show_format cam-1-frame-1.png 
Input #0, png_pipe, from 'cam-1-frame-1.png':
  Duration: N/A, bitrate: N/A
    Stream #0:0: Video: png, rgb24(pc), 3840x2160 [SAR 1:1 DAR 16:9], 25 tbr, 25 tbn, 25 tbc
[FORMAT]
filename=cam-1-frame-1.png
nb_streams=1
nb_programs=0
format_name=png_pipe
format_long_name=piped png sequence
start_time=N/A
duration=N/A
size=11496668
bit_rate=N/A
probe_score=99
[/FORMAT]

 

4. 任务描述:两路/多路视频拼接,同时播放

ffmpeg -i test_1.mp4 -i test_2.mp4 -filter_complex "[0:v]pad=iw*2:ih[a];[a][1:v]overlay=w:0" -pix_fmt yuv420p -y output_result.mp4

从前往后参数的含义分别是:

-i test_1.mp4 指定输入文件的名字,即打算放在左侧播放的视频1

-i test_2.mp4 指定输入文件的名字,及打算放在右侧播放的视频2

-filter_complex "[0:v]pad=iw*2:ih[a];[a][1:v]overlay=w:0"

指的是复杂滤波器的设置。

其中[0:v] [1:v]表示输入的第一个和第二个编号。

pad 用于边界扩充,iw/ih分别是输入视频的宽度和高度。

[0:v]pad=iw*2:ih[a] 表示将第一个输入视频边界扩充,并将扩充好的命名为 [a],方便后续操作。

[a][1:v]overlay=w*1 中的 [a][1:v] 表示将 [1:v] 叠加到 [a] 上去,并且位置从 w 开始,默认是 width=w 处,h 未写表示 0。

同理可得三个视频水平并列放置的命令

ffmpeg -i test_1.mp4 -i test_2.mp4 -i test_3.mp4 -filter_complex "[0:v]pad=iw*3:ih[a];[a][1:v]overlay=w[b];[b][2:v]overlay=w*2:0" -pix_fmt yuv420p -y output_result.mp4

还有一种方法,使用 hstack/vstack 进行组合,实现类似上面的结果

ffmpeg -i /home/cv/Downloads/cam_test_01.mp4 -i /home/cv/Downloads/cam_test_02.mp4 -i /home/cv/Downloads/cam_test_03.mp4 -i /home/cv/Downloads/cam_test_04.mp4 -filter_complex hstack=inputs=4 -shortest -y test_hstack.mp4

其中 -i 用于指示输入数据路径和格式

-filter_complex 用于选择使用的视频滤波器,本例使用水平方向的拼接,filter 的参数 hstac=inputs=4 用于显式指示输入通道数量

-shortest 的选项表示结果的时长与输入数据中时间最短的数据相同

这样得到的结果就是四个输入视频俺从左到右的顺序水平放置。

对输入视频流的旋转可以使用视频滤镜中的 transpose 来实现,不同的值产生不同得结果

  • 0:逆时针旋转90度并垂直翻转
  • 1:顺时针旋转90度
  • 2:逆时针旋转90度
  • 3:顺时针旋转90度后并垂直翻转

结合上面的 overlay 可以实现旋转后组合放置的效果,比如下面这种对四个输入流先逆时针旋转90度然后按左上0-左下1-右下2-右上3的顺序放置的示例。

ffmpeg -hide_banner \
-re -thread_queue_size 32 -i /dev/video0 \
-re -thread_queue_size 32 -i /dev/video1 \
-re -thread_queue_size 32 -i /dev/video2 \
-re -thread_queue_size 32 -i /dev/video3 \
-filter_complex "[0:v]transpose=2[va];[1:v]transpose=2[vb];[2:v]transpose=2[vc];[3:v]transpose=2[vd]; \
[va]pad=iw*2:ih*2[a];[a][vb]overlay=0:h[b];[b][vc]overlay=w:h[c];[c][vd]overlay=w:0" \
-pix_fmt yuv420p -vcodec libx264 -preset ultrafast -tune zerolatency \
-g 50 -sc_threshold 0 -x264-params keyint=25 -vb 50M -vframes 1000 -y overlay_out.mp4

 

5. 任务描述:对给定视频在指定位置添加文字水印

ffmpeg -i ctest.mp4 -vf "drawtext=fontfile=simhei.ttf: text='Original':x=620:y=1920:fontsize=72:fontcolor=yellow:shadowy=2" -y test_dst.mp4

其中:

fontfile 表示字体类型,要确保存在对应的字体库

text 表示要添加的字符串形式的文字内容

fontsize 用来设置字体大小,默认大小为 16

fontcolor 用来设置字体颜色,默认为 Black

x=620:y=1920 表示文字水印放置的位置

如果有多个水印需要放置,中间用逗号隔开即可。

ffmpeg -i test.mp4 -vf "drawtext=fontfile=simhei.ttf: text='Original':x=520:y=1950:fontsize=72:fontcolor=yellow:shadowy=2,drawtext=fontfile=simhei.ttf: text='DaVinci Resolve':x=1770:y=1950:fontsize=72:fontcolor=yellow:shadowy=2, drawtext=fontfile=simhei.ttf: text='Ours':x=3320:y=1950:fontsize=72:fontcolor=yellow:shadowy=2"  -y test_dst.mp4

 

6. 任务描述:从输入视频中裁剪一部分作为输出

利用 ffmpeg 中的 video filter功能,设置指定的裁剪开始位置和裁剪的宽度和高度即可

ffmpeg -i ffmpeg_test.mp4 -vf "crop=w:h:x:y" -y ffmpeg_test_out.mp4

其中 -i 指定输入视频数据

-vf 是 -filter:v 的缩略形式告诉 ffmpeg 使用视频滤波器进行次操作

crop=w:h:x:y 中 w 是输出视频的宽,h 是输出视频的高,x 和 y 是裁剪开始的坐标值,以左上为坐标原点,向右为 x 方向,向下为 y 方向

例如  ffmpeg -i ffmpeg_test.mp4 -vf "crop=960:720:1920:480" -y ffmpeg_test_out.mp4 表示从给定视频中 (1920, 480) 的位置出开始裁剪,

目标视频分辨率为 960x720,所指示的方向坐标和起始点坐标方向相同。

 

7. 任务描述:缩放给定的视频或图像

# 指定宽和高
ffmpeg -i input.png -vf scale=960:640 output.png

# 指定其中一个维度,-1表示等比例
ffmpeg -i input.png -vf scale=960:-1 output_960.png

# 使用factor因子进行缩放
ffmpeg -i input.png -vf scale=iw*2:ih output.png

 

A. 其它常用功能

A.1 获取视频格式信息

ffmpeg -i video.avi

会显示 视频时长、比特率、编码方式、像素格式、分辨率 等信息。

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'test.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf57.71.100
  Duration: 00:00:36.00, start: 0.000000, bitrate: 2781 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661),
    yuv420p, 1920x2160, 2776 kb/s, 50 fps, 50 tbr, 10000k tbn,
    100.01 tbc (default)
    Metadata:
      handler_name    : VideoHandler
Stream info

查看某个视频的总帧数

cv@cv:~/datasets$ ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 -i 1.mp4

等解码完成后会输出信息,比如我的输入视频只有 299 帧,输出结果如下

299

其中

-v error 用于隐藏“info”输出(版本信息等),使输出更简洁。

-count_frames 计算每个流的帧数,并在相应的流部分中报告。

-select_streams v:0 用于选择感兴趣的视频流。

-show_entries stream=nb_read_frames 设置只显示读取的帧数。

-of default=nokey=1:noprint_wrappers=1 将输出格式(也称为“writer”)设置为默认值,不打印每个字段的键(nokey=1),不打印节头和页脚(noprint_wrappers=1)。

A.2 把视频的前30帧转换成一个Animated Gif

ffmpeg -i test.asf -vframes 30 -y -f gif a.gif

 

A.3 将 YUV420P 格式的图像保存成二进制形式的 rawdata ,用ffmpeg转化成正常的 yuv420p 并显示

ffmpeg -f rawvideo -s 7680x3840 -pix_fmt yuv420p -i eqr_000010.bin -y a.bmp
open a.bmp

 

A.4 yuvj420p vs yuv420p

yuvj420p 格式和 yuv420p 格式之间唯一的区别在于:

yuvj420p 使用的是 0-255 的颜色值范围(也就是常见的 PC、JPEG 等标准使用的颜色值范围),

而yuv420p 使用的是 16-240 的颜色值范围(也就是常见的 TV、MPEG 等标准使用的颜色值范围)。

 

A.5 删除视频中相邻的重复帧

使用视频滤波器对相邻重复的帧进行删除,保证每一帧不会连续出现几次

ffmpeg -i test_in.mp4 -vf mpdecimate,setpts=N/FRAME_RATE/TB -y test_out.mp4

 


参考资料

[1] 每天学习一个命令:ffprobe 查看多媒体信息 http://einverne.github.io/post/2015/02/ffprobe-show-media-info.html

[2] ffprobe,ffplay ffmpeg常用的命令行命令 https://juejin.im/post/5a59993cf265da3e4f0a1e4b

[3] ffmpeg 10bit 8bit yuv格式转换 https://blog.csdn.net/baoyongshuai1509/article/details/83927538

[4] YUV420P格式分析 https://blog.csdn.net/yhc166188/article/details/81016916

[5] FFmpeg命令行实现两路/多路视频拼接 合并 合成 同时播放 https://blog.csdn.net/a386115360/article/details/89465633

[6] https://ffmpeg.org/ffmpeg-filters.html#drawtext-1

[7] YUV https://wiki.videolan.org/YUV/

posted @ 2020-02-24 15:41  coffee_tea_or_me  阅读(1512)  评论(0编辑  收藏  举报