ffmpeg, stretch audio to x seconds - audio

I am trying to make an audio file be exactly x second.
So far i tried using the atempo filter by doing the following calculation
Audio length / desired length = atempo.
But this is not accurate, and I am having to tweak the tempo manually to get it to an exact fit.
Are there any other solutions to get this work ? Or am I doing this incorrectly?
My original file is a wav file, and my output in an mp3
Here is a sample command
ffmpeg -i input.wav -codec:a libmp3lame -filter:a "atempo=0.9992323" -b:a 320K output.mp3
UPDATE:
I was able to correctly calculate the tempo by changing the way I am receiving the audio length.
I am now calculating the current audio length using the actual file size and the sample rate.
Audio Length = file size / (sample rate * 2)
Sample rate is something like 16000 Hz. You can get that by using ffprob or ffmpeg.

You are calculating the tempo incorrectly.
Audio length / desired length = atempo
should be:
desired length / Audio length = atempo
This answer was posted as an edit to the question ffmpeg, stretch audio to x seconds by the OP Max Doumit under CC BY-SA 3.0.

Related

ffmpeg duplicate last frame as long as the audio length

I am recording AVI files with Camtasia. For some reason the video stream length is 2,3-5 seconds less than the audio stream.
When I convert the video with ffmpeg from AVI to MP4 it cuts the audio to the video length.
Would duplicating the last frame until the end of the audio be a solution? If yes how can this be done using ffmpeg?
The important thing is to convert the AVI to MP4 using ffmpeg and keep the audio stream of the video complete.
Thank you.
Edit 1: This issue is automatically solved by ffmpeg 2.x somehow but ffmpeg 4.x will cut audio. With the same settings the old version converts correctly.
Edit 2: tpad helped. Thank you very much #kesh. I used
-filter_complex 'tpad=stop=NUMBER_OF_FRAMES:stop_mode=clone'
I tried to get the duration using ffprobe and multiplied the number of seconds with number of frames per second but it was not enough. For each video I had to increase that number with 100,150 frames.
The issue is I cannot detect the exact number of frames to tell tpad. I also tried
-filter_complex 'tpad=stop=-1:stop_mode=clone'
but it freezez while processing.
Is there any other option?

Frequency response of ffmpeg filters

I'm using ffmpeg to decode and encode signal. It works perfectly and I added filters. For example, I'm using such a command :
ffmpeg -re -i /home/dr_click/live.wav -af "anequalizer=c0 f=200 w=100 g=-5 t=0|c1 f=200 w=100 g=-5 t=0, anequalizer=c0 f=1000 w=100 g=3 t=0|c1 f=1000 w=100 g=3 t=0" -acodec pcm_s16be -ar 44100 -ac 2 -f rtp rtp://127.0.0.1:1234
I'm streaming my file, adding 2 filters with 200 Hz and 1000 Hz as central frequency and 100 Hz width and it works.
With such a filter, I know my gain will be -5db at 200Hz. But what is the gain for frequencies at 250 Hz ? Still -5db ? -4.5db ? -3db ? And same question at 350Hz or any other frequency.
What I'm looking for and didn't found is the way to get the frequency response of such a filter for a bandwith from 20Hz to 20kHz. In other words, what I'd like to know for any frequency is : gain = f (frequency) with a given ffmpeg filter
Thank you for your help,
Dr_Click
i'm working on a quite similar issue. Mine is to replace the system wide 15 band graphical LADSPA equalizer (mbeq_1197, controlled by JACK Rack) with an ffmpeg filter. As it is AFAIK impossible to adjust ffmpeg filter parameters during runtime, I have to rely on my already generated JACK EQ settings and need to transfer them to the ffmpeg EQ. Alas, I could not find any two "comparable" EQs: ffmpeg only offers a 18 band "superequalizer". My previous EQ has 15 bands, so I decided to do some interpolations and compare the frequency responses of the old and the new EQ.
Now to answer your question: I'm not an audio engineer, and I'm sure there are more professional ways. But what I found out for now is my current workflow:
Generate some white noise. In Linux you can e.g. use sox oder Audacity. In Audacity do Generate -> Built-in -> Noise... => White noise (1 min should be enough)
Save the file as WAV.
Apply your filter to this WAV: ffmpeg -i whitenoise.wav -af "<your filter>" whitenoise_filtered.wav
Load the filtered file into Audacity and do Analyze -> Plot Spectrum...
The output will be a little scattered because the white noise is not perfect, but this should be negligible.
Good luck!
Flittermice

FFMPEG command to mix audio and video with adjustable volume

I have:
Video file of X length
Audio of Y length
I am trying to achieve an output video that has the following qualities:
The volume level of the added audio should be adjustable
The audio should loop till the end of the video
It should not break even if the input video does not have any audio
I should be able to mute the audio of the source video if needed.
All of the above, in the fastest possible way.
I'm not well versed with FFMPEG, maybe some experts could help.
since you are using a library i assume that you know how to run pure FFmpeg commands
based on your third condition we will divide the solution to two part :
It should not break even if the input video does not have any audio
in order to cover this condition, you can check if there is any audio stream in your video file before running any FFmpeg command with below code:
private boolean isVideoContainAudioStream(String videoPath) {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(videoPath);
String hasAudioStream = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_AUDIO);
if (hasAudioStream != null && hasAudioStream.equals("yes"))
return true;
else
return false;
}
1. Part One :
so if the result of above function is equal to true, your video file contain audio stream so you can run below command :
ffmpeg -i video.mp4 -filter_complex "amovie=/path/to/audio/file/audio.mp3:loop=0,asetpts=N/SR/TB,volume=2.0[audio];[0:a]volume=0.5[sa];[sa][audio]amix[fa]" -map 0:v -map [fa] -vcodec libx264 -preset ultrafast -shortest fout.mp4
in above command we take audio file at a specific path with amovie filter
loop=0, Loop audio infinitely
asetpts=N/SR/TB, Generate timestamps by counting samples
volume=2.0, multiply audio volume by 2.0
video's audio stream is accessible with [0:a] filter pad so we take it and set the volume to half of the input's volume and name it [sa] obviously if you want to mute the audio of the source video you change that part to :
[0:a]volume=0.0[sa]
after that we will mix two audio streams using amix filter and name it [fa], so far we have everything we wanted, and we just want to merge audio and video streams
-vcodec libx264, we are using x264 video encoding because it has lots of configs to gain better performance and speed
-shortest, since we loop audio infinitely, we tell the ffmpeg to continue creating frames until the shortest stream ends (video stream is the short one for sure)
-preset ultrafast, preset is one of the x264 options, ultrafast will give you more encoding speed at the cost of more size in output file, usually using veryfast value for this flag is a good combination of speed and size
2. Part Two :
if the isVideoContainAudioStream function return false (which means your input video is muted) you can run below command:
ffmpeg -i mute_video.mp4 -filter_complex "amovie=/path/to/audio/file/audio.mp3:loop=0,asetpts=N/SR/TB,volume=2.0[audio]" -map 0:v -map [audio] -vcodec libx264 -preset ultrafast -crf 18 -shortest m_fout.mp4
in above command we use another x264 options called CRF
Constant Rate Factor (CRF)
Use this rate control mode if you want to keep the best quality and care less about the file size. This is the recommended rate control mode for most uses.
The range of the CRF scale is 0–51, where 0 is lossless, 23 is the default, and 51 is worst quality possible. A lower value generally leads to higher quality, and a subjectively sane range is 17–28. Consider 17 or 18 to be visually lossless or nearly so; it should look the same or nearly the same as the input but it isn't technically lossless.
The range is exponential, so increasing the CRF value +6 results in roughly half the bitrate / file size, while -6 leads to roughly twice the bitrate.
Choose the highest CRF value that still provides an acceptable quality. If the output looks good, then try a higher value. If it looks bad, choose a lower value.
thats it, there is lots of option for x264 encoder, you can check all available options at this link:
H.264 Video Encoding Guide

FFMPEG change Tone Frequency, keep length (Pitch Audio)

How can I change the Tone frequency.
This Example only pitches it by keeping the old tone frequency and only decrease the length of File.
For Example, I have a constant 100 Herz tone (as mp3) and I want it to change 90 Herz
ffmpeg -i 100h.mp3 -af atempo=100/90 90h.mp3
This Example doesn't work for me, it sounds the same
inputfile Mp3
outputfile Mp3
finally, by combining the asetrate and resample from Gyan, with atempo, the following works and preserves also the audio length
for example: use 0.9 for 90% of the frequenz
ffmpeg -i test.mp3 -af asetrate=44100*0.9,aresample=44100,atempo=1/0.9 output.mp3
Basic method is
ffmpeg -i 100h.mp3 -af asetrate=44100*0.9,aresample=44100 90h.mp3
where 44100 should be replaced with the input sample rate.

How to convert MP3's to constant bitrate using FFMPEG

I have found that MP3's encoded with variable bit rate cause the currentTime property to be reported incorrectly, especially when scrubbing. That has wreaked havok on my app and has been a nightmare to debug.
I believe I need to convert all my MP3's to constant bitrate. Can FFMPEG (or something else) help me do that efficiently?
Props to Terrill Thompson for attempting to pin this down*
I also had issues with HTML5 being inaccurate for large mp3s. Since quality was not a big issue for my audio, I converted to constant bit rate of 8kbps, sample rate 8k, mono and it solved my issues.
You can convert to a contant bit rate for a few files using Audacity (export > save to mp3 > constant bit rate).
Or, using FFMPEG:
ffmpeg -i input.wav -codec:a libmp3lame -b:a 8k output.mp3
If you also want to reduce to mono and a 8k sample rate:
ffmpeg -i input.wav -codec:a libmp3lame -b:a 8k -ac 1 -ar 8000 output.mp3
Using the second compressed an hour of audio to under 5MB.
Something else is going on. currentTime should not be influenced by the fact that you are using variable-bit rate MP3s.
Perhaps the context sampleRate is not the same as the sample rate as the MP3s? That will mess up timing of the audio samples because WebAudio will resample the MP3s to the context sample rate.

Resources