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.com

To 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.com

atempo 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

Using FFMPEG on Docker

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:

../_images/what_aresample_does.png

asetrate set the sample rate without altering the PCM data, in short:

../_images/what_asetrate_does.png

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