术语数字音频和术语数字视频类似,数字视频是一种用于处理和显示可移动图像的技术,而数字音频则是处理声音。数字音频是一种可以使用 PCM(pulse-code modulation:脉冲编码调制)来将声音编码为字节流的技术,它包括捕捉,记录,编辑,编码,复制等多个操作。FFmpeg 支持多种音频格式,如 AAC , MP3 , Vorbis ,WAV , WMA 等。在第二章中我们列出了 FFmpeg 中支持的所有音频格式。
由人耳感知到的声音可以被分为声调(tones)和噪音(noises),声调由物质规则的震动产生,噪音则是由不规则的震动产生的。机械振动以压力波的形式通过空气传递到耳膜,并由它转化为神经信号,最后被人"听到",这就是听觉系统。
由于人类听觉系统的生理限制,我们可以将连续的压力波采用有限的一系列值来描述和代替,然后将这些值转化为数字并保存在电脑中。由于电脑采用二进制,所以常见的音频位深(bit depth)均为2的幂:
模拟音频信号就是每隔一个时间单位取一个样本值,然后将这些样本值按时间顺序排列的数据集。常见的取样频率(sample rates)如下表所示:
量化并取样后的音频可以用多种格式来保存,下表描述了仅能包含音频的特定文件格式(MP3格式除了音频外也能包含图片):
关于音频格式和编解码的详细信息,可参阅《格式转换(Conversion Between Formats)》章节。
声音由物体围绕某个特定位置的震动产生,通常震动被称为声调,可以用不同振幅和频率的正弦波和余弦波表示:
特定音高的连续声调可以使用 sin(tone_height*2*PI*t)
来表示,其中 tone_height 表示要表达的音高相对应的频率,单位Hz;PI 是圆周率常量 ;t 表示时间,单位秒。如果想要使用数学表达式来创建声音,我们可以使用 aevalsrc 这个音频源,它的输出可以被保存为一个音频文件。输出音频可以包含多个通道,每个通道都有 3 个可用的变量表达式来描述,细节如下:
下表包含了从 C1 到 B8 声调的频率,这是以 A4 声调为音调标准的,其频率为 440 Hz,人类可察觉的声音范围为 E2 (男性低音) 到 C6 (女性高音)。
想要产生 A4 声调的声音,命令如下:
ffmpeg -i lavfi -i aevalsrc=sin(440*2*PI*t) -t 10 noteA4.mp3
stereo:立体声
如果想要使用 aevalsrc 音频源来创建多通道声音,我们需要为每一个通道指定其定义表达式,通道之间使用冒号分割,然后跟随两个冒号,最后是通道的布局。可以使用 -layout 选项来布局通道,可用的布局如下:
mono:单声道声音,特指 FC 的一个通道的声音
stereo:立体声,特指为 FL + FR 的两个通道的声音
例如,想要创建一个左通道 为 C4,右通道为 C5 的声音,命令如下:
ffplay -f lavfi -i aevalsrc=sin(261.63*2*PI*t):cos(523.25*2*PI*t)::c=FL+FR
立体音中有些特殊的类型被称为双耳音调(binaural tones:即左右为两个声调):左右两个声调的频率差为 30 Hz 或者更小,且左右两个声调的频率都必须低于 1000 Hz。通过立体声耳机聆听双耳音调会有一些积极的感官效果,如减轻压力,提高学习效率等对大脑功能有增益效果,当然其实际效果和使用的频率和频率差值有关。我们现在创建一个双耳音调:
ffplay -f lavfi -i aevalsrc=sin(495*2*PI*t):cos(505*2*PI*t)::c=FL+FR
声音的音量应小心设置,以免对人耳造成损伤。FFmpeg 提供了 2 中方法来修改音量。第一种是使用 -vol 选项,它接受一个范围在 0~256 的数值,其中 256 为最大值。示例:
ffmpeg -i sound.wav -vol 180 sound_middle_lound.wav
另一种方法是使用 volume filter,详细描述如下:
例如,我们将声音减到原音量的三分之二,命令如下:
ffmpeg -i music.wav -af volumn=2/3 quiet_music.wav
想要将音量增加 10 分贝,命令如下:
ffmpeg -i sound.acc -af volume=10dB louder_sound.acc
想要混合长度不同的多个声音,并指定转变间隔,我们可以使用 amix filter,描述如下:
当有多个不同长度的声音混合时,在某个时刻,必然会有一个较短的声音提前结束,此时如果直接结束该输入,会使得声音变化非常的突兀,因此需要一个时间段来过度变化,而不是突然变化,
如下面的命令,将 4 个输入音频混合为了一个,混合后的长度等于输入音频中的最长时长,且在输入声音之间的转化时间为 5 秒:
ffmpeg -i sound1.wav -i sound2.wav -i sound3.wav -i sound4.wav -filter_complex amix=inputs=4:dropout_transition=5 sounds.wav
想要将多声道的声音降低通道,如立体声降低为单声道,我们可以使用 pan filter,其详细描述如下:
ch_name:表示输出的某一个channel,可以用名称或者通道数来指定;in_name:表示输入的某个channel;gain:表示增益,也就是一个系数,或者音量。而channel_def定义了如何使用in_name指定ch_name。layout指定我们需要输出的channel,而channel_def则具体指定某个channel。
以下是几个降低通道的示例:
ffmpeg -i stereo.wav -af pan=1:c0=0.5*c0+0.5*c1 mono.wav
或者:
ffmpeg -i stereo.wav -af pan=mono mono.wav
ffmpeg -i stereo.wav -af pan=1 mono.wav
ffmpeg -i stereo.wav -af pan=1:c0=0.6*c0+0.4*c1 mono.wav
ffmpeg -i stereo.wav -af pan=1:c0=0.3*c0+0.7*c1 mono.wav
如果不使用 pan filter ,我们也可以降低声音的通道,当源音频文件的通道数大于 2 时,我们可以使用 -ac[:stream_specifier] 选项使用一个数字来指定输出的通道值:
ffmpeg -i 5_1_surround_sound.wav -ac 2 stereo.wav
当我们想在降低声音通道的操作中添加额外的参数,那么我们就只能使用 pan filter。下一个例子自动可以将 3通道,4通道,5通道或7通道的音频降为2通道的立体声:
ffmpeg -i surround.wav -af pan=stereo:FL
ashowinfo filter 可以为每一个输入的音频帧提供相关的细节信息,它会为每个音频帧输出一行信息,其中最多可以有 10 个参数信息,ashowinfo filter 的描述如下:
由于 ashowinfo 的输出可能会非常长,因此我们应该使用 -report 选项将输出保存到文件中,例如:
ffmpeg -report -i audio.wav -af ashowinfo -f null /dev/null
一个 10 秒长,44100 Hz 编码的的立体声,其信息输出如下图所示:
可以使用 earwax filter 来增强输入音频的立体声效果,其描述如下:
例如,想要提高文件 music.mp3 的立体效果,我们可以使用命令:
ffmpeg -i music.mp3 -af earwax -q 1 music_headphones.mp3
-map_channel 选项可以用于修改多个音频参数,其语法如下:
-map_channel [in_file_id.stream_spec.channel_id|-1][:out_file_id.stream_spec]
如果我们想要将输入立体声音频文件的左通道和右通道交换,命令如下:
ffmpeg -i stoero.mp3 -map_channel 0.0.1 -map_channel 0.0.0 ch_switch.mp3
将一个两通道的立体音输入拆分为两个独立的流,然后编码到一个输出文件中(由于 MP3 仅能包含一个音频流,因此输出格式必须为 ACC,OGG,WAV等),命令如下:
ffmpeg -i stereo.mp3 -map 0:0 -map 0:0 -map_channel 0.0.0:0.0 -map_channel 0.0.1:0.1 output.acc
想要将输入的某个通道静音,我们可以在 -map_channel 选项中使用 -1 值。例如,想要静音立体声中的第一个通道,命令如下:
ffmpeg -i stereo12.mp3 -map_channel -1 -map_channel 0.0.1 mono2.mp3
我们可以使用 amerge filter 来将两个音频流混合为一个多通道的流,amerge 有一个参数 inputs,它用来指定输出文件的数量,默认值为 2 。所有的输入文件必须使用相同的取样频率和文件格式编码。例如,想要混合两个单通道的文件为一个立体声流的文件,命令如下(总时长为较短输入的时长):
ffmpeg -i mono1.mp3 -af amovie=mono2.mp3[2];[in][2]amerge stero.mp3
两个输入音频流的同步,可以使用 astreamsync filter 来控制,它有一个参数,它的值由几个变量组成的可选表达式指定。表达式的默认值是 t2-t1 ,意思是总是使用更小的时间戳来推进音频流。