atempo, asetrate, aresample¶
- doc
https://ffmpeg.org/ffmpeg-filters.html#atempo, https://ffmpeg.org/ffmpeg-filters.html#aresample, https://ffmpeg.org/ffmpeg-filters.html#asetrate, https://ffmpeg.org/ffmpeg-filters.html#setpts
atempo¶
Watch on youtube.comTo speed up / slow down audio, you can use “atempo”. “atempo” does not change audio frequency.
[me@host: ~]$ ffplay -af atempo=2.0 wolframtones_01.wav # speed up
[me@host: ~]$ ffplay -af atempo=0.5 wolframtones_01.wav # speed down
[me@host: ~]$ # or you can use calculation like 1/2
[me@host: ~]$ ffplay -af atempo=1/2 wolframtones_01.wav
“atempo” does not accept factors greater than 2 (such as 4/1 or 1/4). So, you need to chain multiple “atempo” filter:
[me@host: ~]$ ffplay -af atempo=2.0,atempo=3.0 wolframtones_01.wav # x 6
[me@host: ~]$ ffplay -af atempo=1.5,atempo=0.5 wolframtones_01.wav # x 0.75
Note
Latest ffmpeg seems to accept range [0.5, 100.0], but the official document says that: “tempo greater than 2 will skip some samples rather than blend them in. If for any reason this is a concern it is always possible to daisy-chain several instances of atempo to achieve the desired product tempo”.
Of course, this filter does not affect the video. To control the video speed, you must use setpts filter:
[me@host: ~]$ ffplay -af atempo=2.0 -vf 'setpts=0.5*PTS-STARTPTS' \
> wolframtones_01.wav # speed up
[me@host: ~]$ ffplay -af atempo=0.5 -vf 'setpts=2.0*PTS-STARTPTS' \
> wolframtones_01.wav # speed down
asetrate, aresample¶
Watch on youtube.comatempo
changes the tempo without changing the frequency. If you want to change the pitch, and you don’t have the latest ffmpeg with --enable-librubberband
, you need to rely on a low-level filter. That is to use asetrate
.
- see also
Think about asetrate
and aresample
at the same time. What the aresample
filter does is quite different from that of the asetrate
filter, but in any case you will have to use both to do what you want.
What aresample
does:
asetrate
set the sample rate without altering the PCM data, in short:
So, asetrate
changes the pitch and the speed.
Now let’s apply asetrate
, but … asetrate
complains “Unknown channel layouts not supported”:
[me@host: ~]$ ffplay wolframtones_03.wav -af 'asetrate=44100*3/4'
ffplay version 3.3.2 Copyright (c) 2003-2017 the FFmpeg developers
built with gcc 7.1.0 (GCC)
configuration: --disable-static --enable-shared --enable-gpl --enable-version3 --enable-cuda --enable-cuvid --enable-d3d11va --enable-dxva2 --enable-libmfx --enable-nvenc --enable-avisynth --enable-bzlib --enable-fontconfig --enable-frei0r --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libfreetype --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenh264 --enable-libopenjpeg --enable-libopus --enable-librtmp --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzimg --enable-lzma --enable-zlib
libavutil 55. 58.100 / 55. 58.100
libavcodec 57. 89.100 / 57. 89.100
libavformat 57. 71.100 / 57. 71.100
libavdevice 57. 6.100 / 57. 6.100
libavfilter 6. 82.100 / 6. 82.100
libswscale 4. 6.100 / 4. 6.100
libswresample 2. 7.100 / 2. 7.100
libpostproc 54. 5.100 / 54. 5.100
nan : 0.000 fd= 0 aq= 0KB vq= 0KB sq= 0B f=0/0
Input #0, wav, from 'wolframtones_03.wav':
Duration: 00:00:30.19, bitrate: 1411 kb/s
Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, 2 channels, s16, 1411 kb/s
[auto_resampler_0 @ 0000000001bf30e0] Cannot select channel layout for the link between filters auto_resampler_0 and Parsed_asetrate_0.
[auto_resampler_0 @ 0000000001bf30e0] Unknown channel layouts not supported, try specifying a channel layout using 'aformat=channel_layouts=something'.
Failed to open file 'wolframtones_03.wav' or configure filtergraph
“I can’t specify the channel layout unless you tell me” is very strange. I don’t think it’s technically impossible. However, there are so many unfair restrictions in ffmpeg, which is just one of them. Give up and follow what ffmpeg says.
Recall: asetrate
changes the pitch and the speed:
[me@host: ~]$ ffplay wolframtones_03.wav \
> -af 'aformat=channel_layouts=stereo,asetrate=44100*4/3'
“* 3/4” reduce pitch and speed (x 0.75):
[me@host: ~]$ ffplay wolframtones_03.wav \
> -af 'aformat=channel_layouts=stereo,asetrate=44100*3/4'
Of course you can use atempo
if you want to restore the speed changed by applying asetrate
. If you are particular about quality, it is better to pay attention to the filter order. I don’t know the correct order, and I’m not particular about it, so I’ll write it carelessly in this example, but the quality may change depending on the filter order if it’s related to interpolation or dropping:
#! /bin/sh
ffmpeg -y -i wolframtones_03.wav \
-af 'aformat=channel_layouts=stereo,
asetrate=44100*4/3,
atempo=3/4' \
wolframtones_03_pc.wav
This result has a strange sampling rate of 58800Hz, which is not standard. Even if you are careless about quality, the device (or player, etc.) that receives it may limit the rate it supports, and you may need to convert it to a standard rate.
You can use aresample
for this purpose:
#! /bin/sh
ffmpeg -y -i wolframtones_03.wav \
-af 'aformat=channel_layouts=stereo,
asetrate=44100*4/3,
atempo=3/4
aresample=44100' \
wolframtones_03_pc.wav
The following example creates and mixes overtones:
[me@host: ~]$ # in this example, there is no unavailable filter on ffmpeg 3.3, but
[me@host: ~]$ # amix of ffmpeg 3.3 seems buggy in this case...
[me@host: ~]$ ffmpeg411="/c/Program Files/ffmpeg-4.1.1-win64-shared/bin/ffmpeg"
[me@host: ~]$ r=2.0
[me@host: ~]$ sr=44100
[me@host: ~]$ "${ffmpeg411}" -y -filter_complex "
> amovie=input.wav
> ,asplit=3[a1][a2][a3];
> [a2]atempo='${r}',asetrate='${sr}/(${r})',aresample=${sr},volume=0.7[a4];
> [a3]atempo='1/(${r})',asetrate='${sr}*(${r})',aresample=${sr},volume=0.2[a5];
> [a1][a4][a5]amix=3,volume=3[a]" -map '[a]' output.wav