Diewuxi

Belive tomorrow will be better, love science and technology, support communication and understanding, always ready for thought turn.

Blog / engineering_technology / computer / software / media / code / FFmepg 笔记

Blog


Article^ Parent

FFmepg 笔记


Date: 2018-11-12 00:00:00
Description: FFmpeg 使用笔记。
Keywords: FFmpeg, 例子, 压缩, 转码
Category: engineering_technology/computer/software/media/code
Tag: ffmpeg, media, encoding
Link: https://www.diewuxi.com/blog/article/87.html

Changelog

* 2022-07-12
    * Add: 视频文件截图
* 2022-02-20
    * Add: 视频封装
* 2020-02-22
    * Modify: itsoffset 选项使用方法
* 2020-02-20
    * Add: 剪裁视频文档内容,补充画面文档内容
    * Add: 数据流时间戳偏移
* 2020-02-19
    * Add: 加字幕
    * Modify: 文目录结构调整:增加 main 为一级目录,其它放到二级目录
    * Add: Too many packets buffered for output stream 0:0 Problem document and my try. 
* 2019-03-05
    * Add: gif 制作
* 2019-01-11
    * Add: 剪裁视频
* 2018-12-15
    * Add: 增加视频拼接 MPEG 容器方法
* 2018-11-22
    * Add: 增加音量调节方法
                        

参数

音频参数

  • -ac 1 指定只保留一个声道,所有声道都融合成一个(这里有个FFmpeg的bug,输出音量会变小)。
  • -ab bitrate 设置音频码率 一般是选择32、 64、96或128这几种

  • -ar freq 设置音频采样率 可以指定为22050、24000、44100或48000,一般来将后两种比较常见;

32k 表示采样率改为32000,通常的高保真音频都是48K左右,这个数值变小,会裁剪掉高音部分,32K会裁掉不少高音,不过普通人如果没个对比,听不出什么问题。 如果音频文件不是音乐,而是人声内容(比如广播),则可以打手一挥设置成22k或16k(电话是16k)

视频参数

  • -r fps 设置帧频,缺省25 一般设置为29.97
  • -b bitrate 设置比特率,缺省200kb/s 可以指定如128、314等数字,对于1500以上则没有效果
  • -qscale 6或4 使用动态码率来设置 可以设置为4或6,4的质量比6的要高

选择数据流

使用 map 参数选择要使用的数据流,视频、音频、字幕不区分,只是包含要使用的数据流 就可以了,具体如何使用,由之后的参数决定。

-map {<file_number>:<stream_number>}
                        

选择 0 号(1.mkv)文件的 0 号数据流和 1 号数据流,然后 0 号数据流编码为 x264 视频,1 号数据流编码为 aac 音频,整个数据用 matroska 容器包装,以 1-new.mkv 文件名输出文件。

ffmpeg -i 1.mkv \
        -map 0:0 -map 0:1 \
        -c:v libx264 -preset ultrafast \
        -c:a aac \
        -f matroska \
        1-new.mkv
                        

视频封装

ffmepg -i {video_file} -i {audio_file} -vcodec copy -acodec copy {output_file}
                        

转格式

FFmpeg 转 3gp:

ffmpeg -y -i **.** \
    -ac 1 \
    -acodec amr_nb -ar 8000 -ab 24 -s 128×96 \
    -vcodec mpeg4 -b 40k -r 8 \
    **.3gp
                        

FFmpeg 转 flv:

ffmpeg \
    -i inputfile.xxx \
    -ab 56 \
    -ar 22050 \
    -qmin 2 -qmax 16 \
    -b 320k \
    -r 15 \
    -s 320×240 \
    outputfile.flv
                        

avi to mkv

ffmpeg \
    -i inputfile.avi \
    -c copy
    outputfile.mkv
                        

"-fflags +genpts" - add this to regenerate packet timestamps (in case of error "Can't write packet with unknown timestamp")

ffmpeg \
    -fflags +genpts \
    -i inputfile.avi \
    -c copy
    outputfile.mkv
                        

压缩

libx264

ffmpeg \
    -i inputfile.xxx \
    -c:v libx264 -x264opts bitrate=xxx\
    -c:a aac \
    outputfile.xxx
                        

bitrate 可以在全局设置如 -b:v 1500K 单位是 bps 在编码器后设置 -c:v libx264 -x264opts bitrate=1500 单位是 Kbps

bitrate 参考值

480P, 720 480, 1800K
720P, 1280 720, 3500K
1080P, 1920 1080, 8500K
                        

我试了试

720P 1500K 也可以看

当然,压缩后的码率高于原始码率就没有意义了。

2018-09-02

480P 800K 也可以看

音乐有损压缩

ffmpeg -i input.mp3 -ac 1 -ar 32k -bit_rate:a 128k output.mp3
                        

尺寸变换

Video option:

-s[:stream_specifier] size (input/output,per-stream)

    Set frame size.
    As an input option, this is a shortcut for the video_size private option, recognized by some demuxers for which the frame size is either not stored in the file or is configurable – e.g. raw video or video grabbers.
    As an output option, this inserts the scale video filter to the end of the corresponding filtergraph.  Please use the scale filter directly to insert it at the beginning or some other place.

    The format is ‘wxh’ (default - same as source).
                        

Video filter scale option:

video filter: scale 

Scale (resize) the input video, using the libswscale library.
The scale filter forces the output display aspect ratio to be the same of the input, by changing the output sample aspect ratio.
If the input image format is different from the format requested by the next filter, the scale filter will
convert the input to the requested format.

width, w
height, h
    Set the output video dimension expression. Default value is the input dimension.
    If the width or w value is 0, the input width is used for the output. If the height or h value is 0, the input height is used for the output.

    If one and only one of the values is -n with n >= 1, the scale filter will use a value that maintains the aspect ratio of the input image, calculated from the other specified dimension. After that it will, however, make sure that the calculated dimension is divisible by n and adjust the value if necessary.
    If both values are -n with n >= 1, the behavior will be identical to both values being set to 0 as previously detailed.

    ...

size, s
    Set the video size. For the syntax of this option, check the (ffmpeg-utils)"Video size" section in the ffmpeg-utils manual.
                        

size format:

Specify the size of the sourced video, it may be a string of the form widthxheight, or the name of a size abbreviation.
                        

转换成 640 x 360

ffmpeg -i input.mp4 -filter:v scale=size=640x360 output.mp4
                        

转换成 720P,宽度按比例自适应,且能被 2 整除

ffmpeg -i input.mkv -filter:v scale=width=-2:height=720 -c:v libx264 output.mkv
                        

Note: 采用 scale 滤镜后 视频不能用 copy,需要重新编码

改变视频FPS

ffmpeg -i input.mp4 -r 30 output.mp4
                        

音量调节

peak normalization, meaning that it will make the loudest part in the file sit at 0 dB instead of something lower. There is also RMS-based normalization which tries to make the average loudness the same across multiple files. To do that, do not try to push the maximum volume to 0 dB, but the mean volume to the dB level of choice (e.g. -26 dB).

Find out the gain to apply

ffmpeg -i video_20181121_224646.mp4 -af "volumedetect" -vn -sn -dn -f null /dev/null
                        

输出

...
[Parsed_volumedetect_0 @ 0x6b3e1c0] n_samples: 16891904
[Parsed_volumedetect_0 @ 0x6b3e1c0] mean_volume: -59.9 dB
[Parsed_volumedetect_0 @ 0x6b3e1c0] max_volume: -24.4 dB
[Parsed_volumedetect_0 @ 0x6b3e1c0] histogram_24db: 4
[Parsed_volumedetect_0 @ 0x6b3e1c0] histogram_25db: 6
...
                        

Apply the volume filter:

ffmpeg -i video_20181120_225032.mp4 -af "volume=24.4dB" -c:v libx264 -x264opts bitrate=500 -c:a aac video_20181120_225032-fixed.mp4
                        

Gif

把视频的前30帧转换成一个Gif :

ffmpeg \
    -i xxx.xxx \
    -vframes 30 \
    -y \
    -f gif \
    xxx.gif
                        

设定时间范围,设置 fps, size

ffmpeg -ss 48:17 -to 48:31 -i 锦衣卫.Secret.Service.Of.The.Imperial.Court.1984.DVDRip.Mandarin.EmbedCHS.rmvb -filter:v "fps=fps=15,scale=width=320:height=-2" -f gif fight.gif
                        

对视频文件截图

ffmpeg -ss 48:17 -to 48:31 -i 锦衣卫.Secret.Service.Of.The.Imperial.Court.1984.DVDRip.Mandarin.EmbedCHS.rmvb -filter:v "fps=fps=15,scale=width=320:height=-2" -f image2 %02d.bmp
                        

剪裁视频

crop filter:

crop

Crop the input video to given dimensions.
It accepts the following parameters:

w, out_w
    The width of the output video. It defaults to iw. This expression is evaluated only once during the filter configuration, or when the ‘w’ or ‘out_w’ command is sent.

h, out_h
    The height of the output video. It defaults to ih. This expression is evaluated only once during the filter configuration, or when the ‘h’ or ‘out_h’ command is sent.

x
    The horizontal position, in the input video, of the left edge of the output video. It defaults to (in_w-out_w)/2. This expression is evaluated per-frame.
y
    The vertical position, in the input video, of the top edge of the output video. It defaults to (in_h-out_h)/2. This expression is evaluated per-frame.

...

Examples
Crop area with size 100x100 at position (12,34).
    crop=100:100:12:34
    Using named options, the example above becomes:
    crop=w=100:h=100:x=12:y=34

Crop the central input area with size 100x100:
    crop=100:100

Crop the central input area with size 2/3 of the input video:
    crop=2/3*in_w:2/3*in_h

Crop the input video central square:
    crop=out_w=in_h
    crop=in_h

Delimit the rectangle with the top-left corner placed at position 100:100 and the right-bottom corner corresponding to the right-bottom corner of the input image.
    crop=in_w-100:in_h-100:100:100

Crop 10 pixels from the left and right borders, and 20 pixels from the top and bottom borders
    crop=in_w-2*10:in_h-2*20

Keep only the bottom right quarter of the input image:
    crop=in_w/2:in_h/2:in_w/2:in_h/2

Crop height for getting Greek harmony:
    crop=in_w:1/PHI*in_w

Apply trembling effect:
    crop=in_w/2:in_h/2:(in_w-out_w)/2+((in_w-out_w)/2)*sin(n/10):(in_h-out_h)/2 +((in_h-out_h)/2)*sin(n/7)

Apply erratic camera effect depending on timestamp:
    crop=in_w/2:in_h/2:(in_w-out_w)/2+((in_w-out_w)/2)*sin(t*10):(in_h-out_h)/2 +((in_h-out_h)/2)*sin(t*13)"

Set x depending on the value of y:
    crop=in_w/2:in_h/2:y:10+10*sin(n/10)
                        

有时可能只需要视频的正中一块,而两头的内容不需要,这时可以对视频进行裁剪(crop),比如有一个竖向的视频 1080 x 1920,如果指向保留中间 1080×1080 部分,可以使用下面的命令:

$ ffmpeg -i a.mov -strict -2 -filter:v crop=1080:1080:0:420 out.mp4
                        

其中的 crop=1080:1080:0:420 才裁剪参数,具体含义是 crop=width:height:x:y,其中 width 和 height 表示裁剪后的尺寸,x:y 表示裁剪区域的左上角坐标。 比如当前这个示例,我们只需要保留竖向视频的中间部分,所以 x 不用偏移,故传入0,而 y 则需要向下偏移:(1920 – 1080) / 2 = 420

补充画面

pad video filter:

pad

Add paddings to the input image, and place the original input at the provided x, y coordinates.
It accepts the following parameters:

width, w
height, h
    Specify an expression for the size of the output image with the paddings added. If the value for width or height is 0, the corresponding input size is used for the output.
    The width expression can reference the value set by the height expression, and vice versa.
    The default value of width and height is 0.
x
y
    Specify the offsets to place the input image at within the padded area, with respect to the top/left border of the output image.
    The x expression can reference the value set by the y expression, and vice versa.
    The default value of x and y is 0.
    If x or y evaluate to a negative number, they’ll be changed so the input image is centered on the padded area.

...

Add paddings with the color "violet" to the input video. The output video size is 640x480, and the top-left corner of the input video is placed at column 0, row 40
    pad=640:480:0:40:violet
    The example above is equivalent to the following command:
    pad=width=640:height=480:x=0:y=40:color=violet

Pad the input to get an output with dimensions increased by 3/2, and put the input video at the center of the padded area:
    pad="3/2*iw:3/2*ih:(ow-iw)/2:(oh-ih)/2"

Pad the input to get a squared output with size equal to the maximum value between the input width and height, and put the input video at the center of the padded area:
    pad="max(iw\,ih):ow:(ow-iw)/2:(oh-ih)/2"

Pad the input to get a final w/h ratio of 16:9:
    pad="ih*16/9:ih:(ow-iw)/2:(oh-ih)/2"

In case of anamorphic video, in order to set the output display aspect correctly, it is necessary to use sar in the expression, according to the relation:
    (ih * X / ih) * sar = output_dar
    X = output_dar / sar
    Thus the previous example needs to be modified to:
    pad="ih*16/9/sar:ih:(ow-iw)/2:(oh-ih)/2"

Double the output size and put the input video in the bottom-right corner of the output padded area:
    pad="2*iw:2*ih:ow-iw:oh-ih"
                        

图片序列与视频的互相转换

ffmpeg -i %04d.jpg output.mp4
ffmpeg -i input.mp4 %04d.jpg
ffmpeg -i input.mp3 -i %04d.jpg output.mp4
                        

提取音乐中的封面图片

ffmpeg -i input.mp3 cover.jpg
                        

截取视频

一般截取视频

ffmpeg \
    -ss START -to POSITION \
    -i INPUT \
    -f FORMAT \
    -codec copy \
    OUTPUT
                        

精确截取视频

将输入的视频先转换成所有的帧都为关键帧的视频,其实就是将所有的帧的编码方式转为帧内编码

ffmpeg -i INPUT -sameq -intra OUTPUT

-i 输入,后面是空格,紧跟着就是输入视频文件;
INPUT 输入文件;
-sameq 表示保持同样的视频质量;(fjc 现在 2018-06-26 没有这个选项了,改成了 -qscale 0)
-intra, 帧内编码;
OUTPUT 输出文件名
                        

再剪裁

ffmpeg \
    -ss START -to POSITION \
    -i INPUT \
    -f FORMAT \
    -codec copy \
    OUTPUT
                        

拼接

MPEG 容器,可以直接连接:

ffmpeg -i "concat:input1.mpg|input2.mpg|input3.mpg" -c copy output.mpg
                        

非 MPEG 容器,但是是 MPEG 编码器(H.264、DivX、XviD、MPEG4、MPEG2、AAC、MP2、MP3 等)

ffmpeg -i q.mp4 -c copy -bsf:v h264_mp4toannexb q.ts
ffmpeg -i r.mp4 -c copy -bsf:v h264_mp4toannexb r.ts
ffmpeg -i "concat:q.ts|r.ts" -c copy -bsf:a aac_adtstoasc qr.mp4
                        

FFmpeg concat 分离器

需要 FFmpeg 1.1 以上版本。先创建一个文本文件filelist.txt:

file 'input1.mkv'
file 'input2.mkv'
file 'input3.mkv'
                        

然后:

ffmpeg -f concat -i filelist.txt -c copy output.mkv
                        

音视频同步修正

2018-09-02

Delay 1 second in first input video and the second input audio just make a copy

ffmpeg -y -itsoffset 00:00:01.000 -i "d:\Video1.mp4" -i "d:\Video1.mp4"
    -map 0:v -map 1:a -vcodec copy -acodec copy
    -f mp4 -threads 2 -v warning "Video2.mp4"
                        

Delay 1 second in second input audio and the first input video just make a copy

ffmpeg -y -i "d:\Video1.mp4" -itsoffset 00:00:01.000 -i "d:\Video1.mp4"
    -map 0:v -map 1:a -vcodec copy -acodec copy
    -f mp4 -threads 2 -v warning "Video2.mp4"
                        

加水印:

ffmpeg \
    -i inputfile.xxx \
    -tagpict “:220:210” \
    -ab 56 \
    -ar 22050 \
    -qmin 2 -qmax 16\
    -b 320k \
    -r 15 \
    -s 320×240 \
    outputfile.flv
                        

-tagpict “:220:210”(在ffmpeg所在目录中寻找0002.mjpg、mask.mjpg两个用作水印处理的图片文件,然后在指定的坐标,比如此处的:220:210,把水印在转码过程中添加到视频文件的每一桢上)

AviSynth加水印:

首先ffmpeg/Mencoder编译时需要–enable-avisynth:

ffmpeg \
    -y \
    -i 1.avs \
    -b 320k \
    rmvb-avs.flv
                        

avs编写格式:

video = DirectShowSource(“rmvb.rmvb”,15).BilinearResize(320,240)
logo = ImageSource(“logo2.jpg”)
logomask = ImageSource(“mask2.jpg”)
overlay(video,logo,mask=logomask)
                        

添加软字幕

从网上看的:

ffmpeg -i 1.mkv -i 1.srt \
        -map 0:0 -map 0:1 -map 1:0 \
        -c:v copy \
        -c:a copy \
        -c:s copy \
        -f matroska \
        1-new.mkv
                        

添加硬字幕

从单独的字幕文件添加:

-filter:v subtitles=filename=<subtitles_filename>

ffmpeg -i 1.mkv \
        -filter:v subtitles=filename=1.srt \
        -map 0:0 -map 0:2 \
        -c:v libx264 -preset fast \
        -c:a aac \
        -f matroska \
        1-new.mkv
                        

从视频文件字幕流添加:

-filter:v subtitles=filename=<video_filename>:si=<subtitle_number>

ffmpeg -i 1.mkv \
        -filter:v subtitles=filename=1.mkv:si=2 \
        -map 0:0 -map 0:2 \
        -c:v libx264 -preset fast \
        -c:a aac \
        -f matroska \
        1-new.mkv
                        

数据流时间戳偏移

AVoption main:

-itsoffset offset (input)
    Set the input time offset.
    offset must be a time duration specification, see (ffmpeg-utils)the Time duration section in the ffmpeg-utils(1) manual.
    The offset is added to the timestamps of the input files. Specifying a positive offset means that the corresponding streams are delayed by the time duration specified in offset.   
                        

视频截成两段了,使用原来的完整字幕:

ffmpeg -itsoffset 00:59:55 -i part2.mkv \
        -i 1.ass \
        -ss 00:59:55 \
        -map 0:0 -map 0:1 -map 1:0 \
        -c copy \
        -f matroska \
        part2-new.mkv
                        

输出视频按照最小时间开始计时,所以如果是使用完整字幕,输出视频时间会是整个原视频的时间。

-ss 选项让视频搜索到截断位置,然后开始处理字幕和视频,视频由于设置了偏移,其实此时并没有视频处理。

Problems

苹果系统的问题

ffmpeg -i input.mp3 -write_xing 0 .... output.mp3
                        

AVI timestamps problem

[avi @ 0x59a1200] Non-monotonous DTS in output stream 0:1; previous: 325543, current: 325515; changing to 325544. This may result in incorrect timestamps in the output file.
                        

result in cannot delay audio with -itsoffset option.

Solve: convert to mkv

Too many packets buffered for output stream 0:0

Some one saying:

Adding -max_muxing_queue_size 99999 seems to be working.
                        

Document:

-max_muxing_queue_size packets (output,per-stream)

When transcoding audio and/or video streams, ffmpeg will not begin writing
into the output until it has one packet for each such stream. While waiting
for that to happen, packets for other streams are buffered. This option
sets the size of this buffer, in packets, for the matching output stream.
The default value of this option should be high enough for most uses, so
only touch this option if you are sure that you need it.
                        

fjc try: first tyr 1024, not working, then 2048, OK.

参考文献

* ffmpeg mencoder视频格式转换 - 私房课(http://www.sifangke.com)
* FFmpeg实用命令 - DavidAQ(http://davidaq.com/tutorial/2014/11/20/ffmpeg-commands.html)
* 使用ffmpeg进行简单的视频编辑 - yanxurui(https://www.yanxurui.cc/posts/tool/2017-10-07-use-ffmpeg-to-edit-video/)
* ffmpeg裁剪合并视频 | IT瘾(http://itindex.net/detail/38530-ffmpeg-合并-视频)
                        

Last modified: 2022-07-12

Comments [0]

There is no comments now.

Write comment(* is necessary, and email is not shown to public)


Diewuxi 2017--2024