9

I know how to change tempo with atempo, but the audio file becomes distorted a bit, and I can't find a reliable way to change pitch. (say, increase tempo and pitch together 140%)

Sox has a speed option, but truncates the volume AND isn't as widely available as ffmpeg. mplayer has a speed option which works perfectly, but I can't output without additional libraries.

I seem to understand ffmpeg doesn't have a way to change pitch (maybe it does recently?) but is there a way to change frequency or some other flags to emulate changing pitch? Looked quite far and can't find a decent solution.

Edit: asetrate:48k*1.4 (assuming originally 48k) doesn't seem to work, still distortion and pitch doesn't really change much.

Edit2: https://superuser.com/a/1076762 this answer sort of works, but the quality is so much lower than sox speed 1.4 option

Community
  • 1
  • 1
Ray C
  • 547
  • 2
  • 7
  • 24

2 Answers2

10

ffmpeg -i <input file name> -filter:a "asetrate=<new frequency>" -y <output file name> seems to be working for me. I checked the properties of both input and output files with ffprobe and there doesn't seem to be any differences that could affect its quality. Although it's true that I've run it a few times and the resulting file on some of those had some artifacts, even if the line of code was the same, so it may be caused by some ffmpeg bug; try to run it again if you aren't satisfied with the quality.

Sizigia
  • 582
  • 5
  • 10
  • You're right that does seem to work. Maybe it's because before I was also touching the `atempo` with the `asetrate` but alone it seems to work. The quality does seem a tad worse than sox or mplayer but it is close enough I suppose. Thanks for the help. Do you know if there is a way to set a multiplicative of the original without checking first? Like instead of 48k*1.4 I can just put 1.4 and it'll increase frequency of asetrate by 1.4? – Ray C Nov 12 '16 at 16:25
  • 3
    Hmm I don't know if there's a direct way to do it, the only thing I can think of is getting the value of the original frequency with ffprobe -just the value, and removing all the extra info so that you can pass it as a variable to the original line of code. You could do it like this: `ffmpeg -i -filter:a "asetrate=$(ffprobe -v error -show_entries stream=sample_rate -of default=noprint_wrappers=1:nokey=1 )*1.4" -y ` – Sizigia Nov 12 '16 at 16:46
6

As of 2022 (though contributed in 2015), FFmpeg has a rubberband filter that works out of the box without any aforementioned ugly, allegedly slow and poor quality and unintuitive workarounds.

To change the pitch using the rubber band filter, you will have to specify the pitch using the frequency ratio of a semi-tone. This is based on using the formula (2^x/12), where x represents the number of semitones you would like to transpose.

For example, to transpose up by one semitone you would use the following command:

ffmpeg -i my.mp3 -filter:a "rubberband=pitch=1.059463094352953" -acodec copy my-up.mp3

To transpose down, simply use a negative number for x.

To alter both properties simultaneously, specify tempo and pitch values. The tempo value is specified as a multiple of the original speed.

The following command transposes down by one semitone and bumps the speed up 4x:

ffmpeg -i slow.mp3 -filter:a "rubberband=pitch=0.9438743126816935, rubberband=tempo=4" -acodec copy fast.mp3

Quality degradation is imperceptible unless measured statistically.

brettv
  • 120
  • 13
tripulse
  • 1,059
  • 11
  • 18
  • This is a great answer! `-acodec copy` was giving me an error: `Filtering and streamcopy cannot be used together.` Which makes sense because this is not a lossless operation. Removing `-acodec copy` worked. – wisbucky Jul 23 '23 at 17:51