admin管理员组

文章数量:1573044

若干年前,写过一篇“技术宅学会几招FFmpeg”。至今仍觉得这篇小文挺实用,时不时会翻出来,对照着使用场景把FFmpeg命令行一抄,直接运行或者简单修改一下参数,就能完成任务,非常方便!有时候,又觉得时过境迁,这篇小文覆盖的使用场景太单薄,亟需补充一下。毕竟自己也换了新的工作环境,碰到了一些新需求。于是,便有了本文。

我们仍然按照使用场景来归类,分为视频/图像、音频、其他工具等。我会视情况,持续更新本文的内容——记得收藏本文的链接哦!

一.视频/图像

Case 100】从最基础的场景开始,在视频文件的指定时间点抽取一帧图像,目标文件格式通过扩展名来控制,可以是.png、.jpg、.webp等:

ffmpeg -ss 5 -i D:\input.mp4 -frames:v 1 D:\snapshot.png

如果需要的是缩略图,或者出于节省存储空间考虑,那就要对图像进行缩放。可以通过scale过滤器来指定你想要的图像宽和高,也可以宽或高只指定一个,另一个用“-1”代替,以保持图像的原始宽高比(确保图像内容不被扭曲):

ffmpeg -ss 5 -i D:\input.mp4 -frames:v 1 -vf scale=120:-1 D:\snapshot.jpg

注:-vf表示简单过滤器。所谓“简单”,是指过滤器只能有一个输入和一个输出。

Case 101】挑战一下,另一种“既要…又要…”的缩略图:既要限定宽和高(比如120x80),又需要保持图像的原始宽高比,图像内容之外的区域用黑色填充:

ffmpeg -ss 5 -i D:\input.mp4 -frames:v 1 -vf "scale='min(120/iw, 80/ih)'*iw:'min(120/iw, 80/ih)'*ih, pad=120:80:(ow-iw)/2:(oh-ih)/2:black" D:\snapshot.webp

解释一下:我们使用了两个过滤器。先使用scale过滤器,iw和ih分别表示源图像的宽和高,相对于目标图像尺寸120x80,分别计算宽和高的缩放比例,选择两者中较小的比例对原始图像进行缩放。然后使用pad过滤器来填充:前两个参数指定目标图像的宽和高(把它想象成一块黑色画布),紧接着的两个参数用来指定实际图像在“画布”上渲染的起始点(左上角)坐标x:y,最后一个参数是填充色。ow和oh分别指代输出图像的宽和高,本例中其实就是120和80。

Case 102】怎样从视频文件里按照一定的间隔(比如10fps)抽取一系列的缩略图呢?

ffmpeg -i D:\input.mp4 -r 10 -vf "scale='min(120/iw, 80/ih)'*iw:'min(120/iw, 80/ih)'*ih, pad=120:80:(ow-iw)/2:(oh-ih)/2:black" -y D:\Thumbnails\Pic-%05d.jpeg

Case 103】有些手机的前置摄像头拍的视频是左右颠倒的,需要做一次水平翻转:

ffmpeg -i D:\input.mp4 -vf hflip D:\flipped.mp4

“买一送一”,送一条垂直翻转:ffmpeg -i D:\input.mp4 -vf vflip D:\flipped.mp4

那么,如何同时做水平和垂直翻转呢?-vf后面可以跟多个过滤器,使用逗号分开即可,注意要加一对引号:

ffmpeg -i D:\input.mp4 -vf "hflip, vflip" D:\flipped2.mp4

还有以前学过的一招,一起汇总在这儿:旋转90度(弧度值为正数表示顺时针,负数表示逆时针),记得要将输出图像的宽和高对调一下:

ffmpeg -i D:\input.mp4 -vf "rotate=a='90*PI/180':ow=ih:oh=iw" D:\rotate90.mp4

当然,上述针对视频文件的处理,对图像文件同样也是适用的。

Case 104】随着智能手机的普及以及UGC短视频内容的风行,现在随处可见竖版视频。如果在某些场景下你偏偏要用横版视频,怎么从竖版视频里抠出一块来呢?该crop过滤器上场啦!举个例子,居中截取与源视频等宽、宽高比是16:9的那一块区域:

ffmpeg -i D:\input.mp4 -vf "crop=in_w:(in_w*9/16):0:(in_h-in_w*9/16)/2" D:\cutout.mp4

Case 105】画中画(或者说在一个视频上叠加另一个视频或图片)是一种常见应用,实现起来也很简单,就是使用overlay复合过滤器。偶然发现一篇不错的文章,里面提到了在视频上叠加计时器的实现,觉得挺巧妙的,所以在这里也记录一下。他的思路分两步:先从一个含有时间戳的视频中裁剪制作出一个计时器视频,然后再将这个计时器视频叠加在主视频上。下面来演练一遍。

第一步:利用一个叫testsrc的视频源,它输出的视频是这样的:

(执行ffplay -f lavfi -i testsrc播放一下就知道了…)

可以定位到时间戳的起始坐标为(224, 94),裁剪两位数字图像的宽度是61,高度是52,生成30秒的计时器视频timer.mp4,完整指令如下:

ffmpeg -f lavfi -i testsrc -vf crop=61:52:224:94 -t 30 D:\timer.mp4

第二步:如果只想在主视频的左上角简单叠加,就这样执行:

ffmpeg -i D:\input.mp4 -i D:\timer.mp4 -filter_complex overlay D:\output1.mp4

如果想把计时器视频缩放后再叠加,比如宽度放大到80(高度指定为-1可以保持原始图像的宽高比),则要利用一个叫movie的简单过滤器(顺便练习一下将叠加的位置改到左下角),如下:

ffmpeg -i D:\input.mp4 -vf "movie=timer.mp4, scale=80:-1[tm]; [in][tm]overlay=0:H-h" D:\output2.mp4

注意:movie后面的filename参数不能带文件路径,于是为了让ffmpeg能顺利找到资源,须将控制台的工作目录设置在包含timer.mp4的地方。

最后补充一下,更完美的方案应该是先执行ffprobe -i D:\input.mp4查看主视频的时长,然后对应地制作等时长的计时器视频,然后再做视频叠加。

Case 106】发现60fps的视频在某些手机上倍速播放时直接卡住了,估计是帧率太高,CPU忙不过来!这时候可以通过-r把帧率降下来试试。
ffmpeg -i D:\input.mp4 -r 30 D:\out30fps.mp4

假设采用的是H.264编码器,还可以通过profile和level来调整画质。可选的profile有:baseline、extended、main、high,再通过level来控制比特率(这里有更详细的对照表)。根据应用领域的不同,baseline profile多应用于实时通信领域,main profile多应用于流媒体领域,high profile则多应用于广电和存储领域。还要注意,有些低端设备或早期的设备只能解码baseline。
ffmpeg -i D:\input.mp4 -profile:v baseline -level 3.0 D:\output1.mp4
ffmpeg -i D:\input.mp4 -profile:v main -level 4.2 D:\output2.mp4
ffmpeg -i D:\input.mp4 -profile:v high -level 5.1 D:\output3.mp4

Case 107】Case 103谈到了画面颠倒的问题。再补充一种情况:手机横握时(玩游戏)的录屏,录制的视频文件实际的宽高却是720x1556,妥妥的竖版视频啊,而在电脑上实际播放时却是横版的1556x720,完美呈现!怎么做到的呢?使用ffprobe观察后发现:

Metadata:

      creation_time   : 2024-03-20T03:24:46.000000Z

      handler_name    : VideoHandler

      vendor_id       : FFMP

    Side data:

      displaymatrix: rotation of 90.00 degrees

原来是displaymatrix在起作用!播放时会自动将画面旋转90度,于是竖版视频一下子就变横版了!如果有机会对视频文件进行重新编码的话,为了追求最大的兼容性,建议抛弃displaymatrix。不过貌似不能直接修改这个属性哦,而是要对视频进行重新编码才能做到。网上几乎找不到displaymatrix的详细说明,ffmpeg_filter.c源代码里有一些线索,可以管中窥豹。displaymatrix取值为下面这个数串时表示不做任何旋转:

ffmpeg -i INPUT.mp4 -metadata:s:v displaymatrix="0 1 0 0 0 1 0 0 0" -c:a copy OUTPUT.mp4

或者使用transpose滤镜,先顺时针旋转90度,再逆时针旋转90度,也能达到目的:

ffmpeg -i INPUT.mp4 -vf "transpose=1" -codec:v libx264 -c:a copy OUTPUT1.mp4

ffmpeg -i OUTPUT1.mp4 -vf "transpose=2" -codec:v libx264 -c:a copy OUTPUT2.mp4

从这个例子也可以看出,仅凭视频文件的宽高比例来判断源文件是横版视频还是竖版视频,未必准确哦!以Android App开发为例,需要通过MediaMetadataRetriever获取METADATA_KEY_VIDEO_ROTATION的值来综合判断。

二.音频

【Case 200】实验室的Matlab算法能接受的数据格式可能仅限于.wav,而客户提供的素材可能是任意一种压缩格式,需要做一次转换:

ffmpeg -i D:\input.m4a D:\output.wav

好简单吧,通过输出文件的扩展名.wav就能控制数据格式。当然,如果想要生成.mp3或.ogg压缩格式,如法炮制,把输出文件名改成output.mp3或output.ogg即可。如果拿到的素材是视频文件,只想提取其中的音频,用法也是类似的(-vn表示丢弃视频数据,这个参数是可选的):

ffmpeg -i D:\input.mp4 -vn D:\output.wav

【Case 201】常见的音频采样频率有11025Hz、22050Hz、24000Hz、44100Hz(CD音质)、48000Hz、96000Hz等。如何进行改变呢?

ffmpeg -i D:\input.m4a -ar 48000 D:\output.wav

【Case 202】假如客户给的素材是5.1声道的,而我们只能处理单声道或双声道,怎么办?

ffmpeg -i D:\input.m4a -ac 1 D:\output.wav

如果输出的是纯PCM数据文件,需要使用-f来限定格式:

ffmpeg -i D:\input.m4a -ac 1 -acodec pcm_s16le -f s16le D:\output.pcm

【Case 203】常见的采样精度/位深有8位、16位、24位、32位等,即单个声道每个采样点用多少Bits来表示。如果要改变位深,则需使用-acodec来指定编码器(如果想查询当前有哪些可用的编码器,参见Case 300),可选值为:pcm_u8、pcm_s16le、pcm_s24le、pcm_s32le等,其中“u”表示无符号数,“s”表示有符号数,“le”表示little-endian(即低字节在前的多字节数据格式):

ffmpeg -i D:\input.m4a –acodec pcm_s24le D:\output.wav

注:-acodec与-c:a是等价的。

【Case 204】如何改变音量呢?使用-af音频过滤器,volume=1表示正常音量,=0.5表示变为一半,=2表示变为2倍。volume的取值也可以带上dB单位,正数表示音量增加xxdB,负数表示音量减小xxdB:

ffmpeg -i D:\input.m4a -af volume=2 D:\output.wav

ffmpeg -i D:\input.m4a -af volume=-2dB D:\output.wav

【Case 205】如果目标文件是一种压缩格式,我们可能还想使用-ab来指定它的码率/bitrate(CBR-恒定码率),以控制音质(码率越高、音质越好):

ffmpeg -i D:\input.m4a -ab 128k D:\output.mp3

注:-ab与-b:a是等价的。

或者也可以用-aq(取决于特定的编码器,VBR-可变码率,取值越小,码率越高):

ffmpeg -i D:\input.m4a -aq 2 D:\output2.mp3

【Case 206】如何将多个音频文件首尾相连合成为一个?假设有四个源文件,分别是input1.m4a、input2.wav、input3.mp3、input4.mp4(格式不限),然后要使用-filter_complex复合过滤器(-lavfi是其等价形式),“concat”之前的[0:0]表示第一个输入源的0号输出(注意:索引都是从0开始的,对于有多路输出的源文件,0号输出是视频流,1号输出是音频流),[1:0]表示第二个输入源的0号输出,以此类推;“concat”之后的n=4表示总共有4路流参与合成,v=0表示丢弃视频数据,a=1表示为合成一路音频流:

ffmpeg -i D:\input1.m4a -i D:\input2.wav -i D:\input3.mp3 -i D:\input3.mp4 -filter_complex "[0:0][1:0][2:0][3:1]concat=n=4:v=0:a=1" –ab 128k –y D:\concat.mp3

脑补这样一张图:

【Case 207】继续讨论多文件混合的场景,如果我们要的不是首尾相连,而是混音呢?那就要用到amerge这个复合过滤器了:

ffmpeg -i D:\input1.m4a -i D:\input2.wav -filter_complex "[0:0][1:0]amerge=inputs=2" –ab 128k D:\merge.mp3

需要注意的是,合成的文件时长以较短的那个为准——这个有点让人无法接受!有个“笨”办法,就是使用-stream_loop让较短的那个输入文件循环输出,像这样:

ffmpeg -stream_loop 2 -i D:\input1.m4a -i D:\input2.wav -filter_complex "[0:0][1:0]amerge" –ab 128k -y D:\merge.mp3

很别扭呀!还是来看看更为强大的amix过滤器吧,它可以通过duration来指定目标文件的时长以哪个为准(可选值为longest、shortest、first),还可以通过weights指定各路流的混音权重(缺省均为1/N):

ffmpeg -i D:\input1.m4a -i D:\input2.wav -i D:\input3.mp3 -filter_complex "[0:0][1:0][2:0]amix=inputs=3:duration=longest:weights='0.1 0.1 0.8'" –ab 128k D:\mix.mp3

【Case 208】继续深入探讨:在混音时,可以为各个音效文件指定在时间线上的开始时间吗?答案是肯定的。我们这次把最长的主音频文件作为第一个输入源,然后通过adelay过滤器将第二个音效文件延迟5秒开始,将第三个音效文件延迟至第30秒开始(delays参数值,不带单位时默认为毫秒,小写s表示秒,大写S表示采样点数量;可以为各个声道分别指定延迟时间,或者通过all=1为所有声道指定相同的延时):

ffmpeg -i D:\input1.m4a -i D:\input2.wav -i D:\input3.mp3 -filter_complex "[1:a]adelay=delays=5s:all=1[a1]; [2:a]adelay=delays=30s:all=1[a2]; [0:a][a1][a2] amix=inputs=3:duration=first:weights='0.6 0.2 0.2'" –ab 128k -y D:\mix.mp3

值得注意的是,这次我们换了一种标注方法:[1:a]表示第二个输入源的音频输出,经过adelay处理之后把输出流标记为[a1];[2:a]表示第三个输入源的音频输出,经过adelay处理之后把输出流标记为[a2];然后第一个输入源的音频输出流[0:a]与[a1]和[a2]一起喂给amix过滤器进行混音。目标文件的时长以第一个输入源为准。各路流的混音比例分别是60%、20%、20%(加起来等于100%)。

【Case 209】一个立体声音频流,将其中一个声道的数据清零(静音),输出仍然是立体声。
将右声道静音:ffmpeg -i D:\input.wav -af "pan=stereo|c0=c0" D:\right_muted.wav
将左声道静音:ffmpeg -i D:\input.wav -af "pan=stereo|c1=c1" D:\left_muted.wav

【Case 210】如何从一个立体声音频流中抽取一个声道的数据,然后生成一个单声道音频文件?本可以使用-map_channel,但这个参数被废弃了。官网建议使用pan过滤器,用法如下:
只取左声道:ffmpeg -i D:\input.wav -af "pan=1c|c0=c0" D:\mono_left.wav
只取右声道:ffmpeg -i D:\input.wav -af "pan=1c|c0=c1" D:\mono_right.wav
雨露均沾(左90%+右10%):ffmpeg -i D:\input.wav -af "pan=1c|c0=0.9*c0+0.1*c1" D:\mono_right.wav
注:对比Case 202,-ac 1是会自动进行多声道混音的。

【Case 211】将一个音频文件的波形图画出来,可以利用showwavespic过滤器很容易做到。用s参数指定输出图像的宽和高(图像宽度影响波形的疏密);split_channels取值为1表示各个声道分开画,取值为0表示所有声道重叠画在一起:
ffmpeg -i D:\input.m4a -filter_complex showwavespic=s=1280x720:split_channels=1 D:\waveform.png

【Case 212】玩一玩多声道音频!假设有6个独立的Wave文件,想要把它们合成为一个5.1声道的.ogg文件,怎么实现呢?先来看看5.1声道或者7.1声道的命名规则,ChatGPT (v3.5) 是这么说的:

// 5.1声道
Front Left
Front Center
Front Right
Surround Left
Surround Right
Subwoofer (LFE - Low Frequency Effects)

// 7.1声道
Front Left
Front Center
Front Right
Surround Left
Surround Back Left
Surround Back Right
Surround Right
Subwoofer (LFE - Low Frequency Effects)

但是请注意,这些命名与FFmpeg的定义有细微的差别哦!还是通过执行ffmpeg –layouts命令来查看一下吧:

  1. 5.1声道为(注意与6.0声道是不同的!):FL+FR+FC+LFE+BL+BR
  2. 7.1声道为:FL+FR+FC+LFE+BL+BR+SL+SR

再来看本条Case的任务,使用join过滤器即可:

ffmpeg -i D:\input1.wav -i D:\input2.wav -i D:\input3.wav -i D:\input4.wav -i D:\input5.wav -i D:\input6.wav -filter_complex "join=inputs=6:channel_layout=5.1:map=0.0-FL|1.0-FR|2.0-FC|3.0-BL|4.0-BR|5.0-LFE" D:\mixed_5_1.ogg

join过滤器的参数说明:inputs表示输入的个数,channel_layout表示输出的格式(注意这里取值5.1还是6对于声道命名的影响),然后通过map来定义5.1声道的映射,比如0.0-FL表示第一个输入文件的0号声道映射到输出文件的FL声道,1.0-FR表示第二个输入文件的0号声道映射到输出文件的FR声道,以此类推。

使用音频编辑软件(e.g. Audacity)打开mixed_5_1.ogg,验证6个声道的数据是否符合预期。你会发现个问题,使用join过滤器合成的mixed_5_1.ogg文件的时长有些奇怪,它是以所有输入文件中时长最短的那个为准的——这也许不是我们期望的!

如果所有输入文件是等时长的,上面的问题就不是问题。如若不然,我们可以使用amerge过滤器来解决这个问题,并用channelmap来做声道映射。我们把时长最长的输入文件放在第一个,以它的时长为准,它的apad填充的静音数据时长为0(即pad_len=0);其他的输入文件也都用apad过滤器来填充静音数据(以弥补自身时长的不足),而且因为apad不带任何参数,表示无限添加静音数据。完整的命令行如下:

ffmpeg -i D:\input1.wav -i D:\input2.wav -i D:\input3.wav -i D:\input4.wav -i D:\input5.wav -i D:\input6.wav -filter_complex "[0]apad=pad_len=0[FL];[1]apad[FR];[2]apad[FC];[3]apad[BL];[4]apad[BR];[5]apad[LFE];[FL][FR][FC][BL][BR][LFE]amerge=inputs=6,channelmap=map=FL-FL|FR-FR|FC-FC|BL-BL|BR-BR|LFE-LFE" D:\mixed_5_1_long.ogg

感觉还是有些别扭,因为必须前置判断哪个输入文件最长。尝试像【Case 207】那样使用 amix代替amerge ,未成功!

【Case 213】反过来玩一下,把一个多声道音频文件的各个声道都拆出来,分别保存为一个Wave文件。使用channelsplit可以轻松实现:

ffmpeg -i D:\mixed_5_1_long.ogg -filter_complex "channelsplit=channel_layout=5.1[FL][FR][FC][LFE][SL][SR]" -map [FL] D:\Split\front_left.wav -map [FR] D:\Split\front_right.wav -map [FC] D:\Split\front_center.wav -map [LFE] D:\Split\lfe.wav -map [SL] D:\Split\side_left.wav -map [SR] D:\Split\side_right.wav

【Case 214】使用amerge过滤器实现了5.1声道的OGG文件合成。那么,怎样生成7.1声道的音频文件呢?参考Case 212依葫芦画瓢就行了吧?结果得到如下的错误:

[Parsed_channelmap_9 @ 000001ba8393da40] input channel 'LFE' not available from input layout 'hexadecagonal'
[Parsed_channelmap_9 @ 000001ba8393da40] Failed to configure input pad on Parsed_channelmap_9
Error reinitializing filters!
Failed to inject frame into filter network: Invalid argument
Error while processing the decoded data for stream #7:0

怎么被识别成了要生成16声道(hexadecagonal)的文件?百思不得其解!16声道的定义里确实没有叫LFE的声道。也罢,不生成7.1了,生成8声道数据吧,即使用octagonal      FL+FR+FC+BL+BR+BC+SL+SR这组命名,执行命令行如下:

ffmpeg -i D:\input1.wav -i D:\input2.wav -i D:\input3.wav -i D:\input4.wav -i D:\input5.wav -i D:\input6.wav -i D:\input7.wav -i D:\input8.wav -filter_complex "[0]apad=pad_len=0[FL];[1]apad[FR];[2]apad[FC];[3]apad[BL];[4]apad[BR];[5]apad[BC];[6]apad[SL];[7]apad[SR];[FL][FR][FC][BL][BR][BC][SL][SR]amerge=inputs=8,channelmap=map=FL-FL|FR-FR|FC-FC|BL-BL|BR-BR|BC-BC|SL-SL|SR-SR" D:\mixed_8c.ogg

执行过程中有下面这个报错,但mixed_8c.ogg文件还是生成了,而且播放正常。保险起见,把目标文件改成D:\mixed_8c.wav就好了。

[libvorbis @ 00000206f7087540] octagonal not supported by Vorbis: output stream will have incorrect channel layout.

或者,我们不用channelmap了,改用pan过滤器:

ffmpeg -i D:\input1.wav -i D:\input2.wav -i D:\input3.wav -i D:\input4.wav -i D:\input5.wav -i D:\input6.wav -i D:\input7.wav -i D:\input8.wav -filter_complex "[0]apad=pad_len=0[FL];[1]apad[FR];[2]apad[FC];[3]apad[BL];[4]apad[BR];[5]apad[SL];[6]apad[SR];[7]apad[LFE];[FL][FR][FC][BL][BR][SL][SR][LFE]amerge=inputs=8,pan=7.1|c0<c0+c1|c1<c2+c3|c2<c4+c5|c3<c6+c7|c4<c8+c9|c5<c10+c11|c6<c12+c13|c7<c14+c15[aout]" -map [aout] -y D:\mixed_7_1_pan.ogg

pan的参数再解释一下,第一个参数7.1指明了输出文件的声道格式,c0<c0+c1表示将第一个输入文件(假设输入文件都是双声道)的两个声道相加赋值给输出文件的第一个声道,c1<c2+c3表示将第二个输入文件的两个声道相加赋值给输出文件的第二个声道,依次类推。放心,官网还有这么一段说明:If the ‘=’ in a channel specification is replaced by ‘<’, then the gains for that specification will be renormalized so that the total is 1, thus avoiding clipping noise(削波噪声).

如果输入文件都是单声道的,命令行可以写成这样:

ffmpeg -i D:\input1.wav -i D:\input2.wav -i D:\input3.wav -i D:\input4.wav -i D:\input5.wav -i D:\input6.wav -i D:\input7.wav -i D:\input8.wav -filter_complex "[0]apad=pad_len=0[FL];[1]apad[FR];[2]apad[FC];[3]apad[BL];[4]apad[BR];[5]apad[SL];[6]apad[SR];[7]apad[LFE];[FL][FR][FC][BL][BR][SL][SR][LFE]amerge=inputs=8,pan=7.1|c0=c0|c1=c1|c2=c2|c3=c3|c4=c4|c5=c5|c6=c6|c7=c7[aout]" -map [aout] -y D:\mixed_7_1_pan2.ogg

【Case 215】怎么把一个8声道的音频文件与一路视频数据合并成一个.mp4文件?这回求助于ChatGPT,倒是一蹴而就!主要是使用-map来做映射,-map 0:v表示从第一个输入文件里提取视频流,-map 1:a表示从第二个输入文件里提取音频流,两路流最终都写入一个输出文件:

ffmpeg -i D:\video.mp4 -i D:\mixed_8c.wav -c:v copy -c:a aac -map 0:v -map 1:a -ac 8 D:\mixed_v_a8c.mp4

值得注意的是,如果已知输入音频文件mixed_8c.wav是8声道的,后面的-ac 8是不必要的;如果输入文件没有8个声道,使用-ac 8补足的声道实际上都是静音数据。这个在Case 217里再展开。

Case 216】再来练习一下apad过滤器。如果手头有个5s的.wav文件,想在5s之后补充静音数据,把它做成8s长度的。可以使用apad过滤器的whole_dur参数来实现(点击这里查看FFmpeg表示时长的格式说明):

ffmpeg -i D:\audio.wav -af apad=whole_dur=8 D:\Media\audio_8s.wav

Case 217】关于多声道音频文件,再补充一点:FFmpeg有一个默认策略来处理“下混”(down-mix)和“上混”(up-mix),使用-ac指定声道数量就可以轻松实现。Case 202实际上已经演练了“下混”,我们再来试试“上混”吧——将一个立体声音频文件转成一个8声道文件:

ffmpeg -i D:\audio_2c.wav -ac 8 D:\audio_8c.wav

结果发现,除了原始的两个声道数据之外,其余6个声道都填充了静音数据😂 怎么让这6个声道不要这么“摆烂”呢?其实可以像Case 210那样使用pan过滤器(因为pan的第一个参数7.1已经指明了输出的声道格式,所以这里就不再需要-ac 8了):

ffmpeg -i D:\audio_2c.wav -af pan="7.1|c0=c0|c1=c1|c2=c0|c3=c1|c4=c0|c5=c1|c6=c0|c7=c1" D:\audio_8c_better.wav

pan的参数里,c0=表示输出文件第一个声道的取值,c1=表示输出文件第二个声道的取值,以此类推。注意:“|”前后不要有空格!!!

Case 218】有些看似普普通通的MP4文件,在手机上用系统播放器却播放失败!使用ffprobe查看格式,发现像素格式是yuv444p(progressive),可能Android播放器对这种格式不太友好吧?可以使用下述命令行将其转为最常见的yuv420p格式:

ffmpeg -i D:\source.mp4 -c:v libx264 -pix_fmt yuv420p D:\ouput.mp4

使用ffmpeg -pix_fmts 还可以查看所有的像素格式。

三.其他工具

【Case 300】查看FFmpeg自带的编解码器、文件容器格式:

ffmpeg –codecs
ffmpeg –decoders
ffmpeg –encoders
ffmpeg –formats

【Case 301】有时候需要录屏,但又懒得去安装一款第三方录屏软件。可以这样:

ffmpeg -f gdigrab -i desktop D:\screenshots.mp4

注:按下“Q”键或者 Ctrl+C 即可停止录屏。
如果机器上装了360,有可能出现“拒绝访问”错误!

【Case 302】基于上述录屏命令,在视频右下角加上文字水印:

ffmpeg -f gdigrab -i desktop -vf drawtext="fontsize=80:fontcolor=white:text='TEST':x=(w-text_w-10):y=(h-text_h-10)" -y D:\screenshots.mp4

【Case 303】基于上述录屏命令,改成在视频右上角加上图片水印:

ffmpeg -f gdigrab -i desktop -i D:\logo.png -filter_complex "[0:0][1:0]overlay=x=main_w-overlay_w-10:y=0" -y D:\screenshots.mp4

【Case 304】通过笔记本电脑的内置摄像头采集一段视频。摄像头的名字未必总是“Integrated Camera”,可能因不同机型而不同,可以在Windows系统的“设备管理器 | 照相机”下查看(或者执行ffmpeg -list_devices true -f dshow -i dummy):

ffmpeg -f dshow -i video="Integrated Camera" D:\capture.mp4

注:按下“Q”键或者 Ctrl+C 即可停止采集。

【Case 305】如果通过笔记本电脑的内置摄像头只想截取一张图呢?可以从上述采集生成的视频中截取,也可以通过下述命令来截取:

ffmpeg -f dshow -i video="Integrated Camera" -f image2 -vframes 1 -y D:\snapshot.jpg

当然,在截图之前最好预览一下,调整好人物在摄像头前的站位:

ffplay -f dshow -i video="Integrated Camera"

========
官网资料:

http://ffmpeg/ffmpeg.html#Audio-Options

 http://ffmpeg/ffmpeg.html#Video-Options

http://ffmpeg/ffmpeg-filters.html

本文标签: ffmpeg