FFMPEG trim and concat mp3 without re-encoding - audio

Good Day,
I would like to know if it is possible to "join" a portion of an mp3 file to another without re-encoding using ffmpeg. I need to prepend an audio mp3 file with silence to ensure it is 60 seconds long.
i.e if my audio file a.mp3 is 40 seconds I need to prepend 20 seconds of silence without re-encoding.
My thoughts on doing this was to have a 60 second long silence mp3 (silence.mp3) at the same CBR and sample rate of my audio (44100 and 40kbps). I then need to "trim" this file and concat/join with the audio file (a.mp3) appropriately.
I have a linux script that computes the required seconds to prepend and I tried using the following filter_complex expression:
ffmpeg -i silence.mp3 -i a.mp3 -filter_complex "[1]adelay=20000[b];[0][b]amix=2" out.mp3
This works however takes too long as it performs re-encoding which takes a long to process. Im looking for a non re encoding solution that can just join the correct sized portion of silence.mp3 to a.mp3. The commands would need to include as a parameter the length of silence that must be used from the overall silence.mp3 file.
Any advise is appreciated.

Your requirement is to not re-encode and yet that's what your method does.
Let's say you have a silent MP3 of the required duration ready.
Create a text file, list.txt
file silence.mp3
outpoint 20
file main.mp3
and join
ffmpeg -f concat -i list.txt -c copy merged.mp3
I assume the properties of silence.mp3 match the main audio file, in terms of channel count and sampling rate.

Related

Is there a way to ensure mp3 duration accuracy with variable bit rate using FFMPEG?

In our application, we are processing audio files using ffmpeg. Specifically, we use the NodeJS library fluent-ffmpeg, (npm link).
Our audio files are generated from various text to speech providers. We recently noticed that when we converted audio using ssml to add pauses to the generated audio, the duration on the file is no longer correct. Upon further investigation, we noticed that the standard audios were also incorrect, just more accurate overall due to the more consistent data. When we put a pause at the beginning of the audio, the estimate was the worst, overshooting it by a very large margin (e.g., a 25s audio clip would read as 3 minutes long, but skip to the end when playing past the 25s mark.
I did some searching and research into the structure of MP3 files, and to me it seems like the issue is because the duration gets estimated by various audio players. Windows media player is an example, but Firefox's web player seems to also do this. I tried changing the ffmpeg command from using .audioQuality(0), which sets ffmpeg to use VBR, to .audioBitrate(320), which tells ffmpeg to use a constant bitrate.
For reference, the we are using libmp3lame, and the full command that gets run is the following, for the VBR and CBR cases respectively:
For VBR (broken durations): ffmpeg -i <URL> -acodec libmp3lame -aq 0 -f mp3 pipe:1
For CBR (correct duration): ffmpeg -i <URL> -acodec libmp3lame -b:a 320k -f mp3 pipe:1
Note: we then pipe the output to the requesting client application after sending the appropriate file headers, hence the pipe:1 output. The input is a cloud storage url where the source file is located
This fixes our problem of having a correct duration, and it makes sense to me why this would fix it if the problem was because the duration is being estimated by some of these players / audio consumers. But, this came at the cost that the file size was significantly larger, which also makes sense to me. While testing we found that compared to the same file in WAV, the VBR mp3 was about 10% of the WAV file size, while the CBR mp3 was still 50% of the WAV file size. This practically defeats the purpose of supporting the mp3 format for our use-case, which is a smaller but slightly lossy alternative to the large WAV file.
While researching, I found that there can be ID3 tags in a chunk at the beginning of the mp3 file, specifying information for the consumer of the audio to know the duration before potentially having processed the whole file. But, I also found that there doesn't seem to be a standard, at least for duration. More things like song title, album, artist, etc.
My question is, is there a way to get the proper duration onto an mp3 file, preferably via some ffmpeg mechanism, while still using VBR? Thanks!
FFmpeg does write a Xing header by default with duration info. However, that value is only known after the entire stream data has been received, so ffmpeg has to seek to the head to write it. Since you're piping the output, that can't be done.
Write the file locally or to some seekable destination, and then upload.

squish mp3 file to set duration

I have a mp3 file(around 7 mins) and I want to shorten the file to 1 minute. But I don't want to just cut it. I want to squish the file without changing the pitch(like speed up).
I already tried with FFmpeg, but FFmpeg just cuts it off.
For info: The file is stored in the fs.
This is doable with ffmpeg. Try using the atempo filter like this:
ffmpeg -i original.mp3 -filter:a "atempo=7.0" -vn seven-times-as-fast.mp3
It should produce a new mp3 file in the same pitch, just seven times faster.

mkv file out of sync with linear drift

I have a bunch of mkv files, with FLAC as the audio codec and FFV1 as the video one.
The files were created using an EasyCap aquisition dongle from a VCR analog source. Specifically, I used VLC's "open acquisition device" prompt and selected PAL. Then, I converted the files (audio PCM, video raw YUV) to (FLAC, FFV1) using
ffmpeg.exe -i input.avi -acodec flac -vcodec ffv1 -level 3 -threads 4 -coder 1 -context 1 -g 1 -slices 24 -slicecrc 1 output.mkv
Now, the files are progressively out of sync. It may be due to the fact that while (maybe) the video has a constant framerate, the FLAC track has variable framerate. So, is there a way to sync the track to audio, or something alike? Can FFmpeg do this? Thanks
EDIT
On Mulvya hint, I plotted the difference in sync at various times; the first column shows the seconds elapsed, the second shows the difference - in secs. The plot seems to behave linearly, with 0.0078 as a constant slope. NOTE: measurements taken by hands, by means of a chronometer
EDIT 2
Playing around with VirtualDub, I found that changing the framerate to 25 fps from the original 24.889 (Video->Frame rate...->Change frame rate to) and using the track converted to wav definitely does work. Two problems, though: VirtualDub crashes when importing the original FFV1-FLAC mkv file, so I had to convert the video to H264 to try it out; more, I find it difficult to use an external encoder to save VirtualDub output.
So, could I avoid using VirtualDub, and simply use ffmpeg for it? Here's the exported vdscript:
VirtualDub.audio.SetSource("E:\\4_track2.wav", "");
VirtualDub.audio.SetMode(0);
VirtualDub.audio.SetInterleave(1,500,1,0,0);
VirtualDub.audio.SetClipMode(1,1);
VirtualDub.audio.SetEditMode(1);
VirtualDub.audio.SetConversion(0,0,0,0,0);
VirtualDub.audio.SetVolume();
VirtualDub.audio.SetCompression();
VirtualDub.audio.EnableFilterGraph(0);
VirtualDub.video.SetInputFormat(0);
VirtualDub.video.SetOutputFormat(7);
VirtualDub.video.SetMode(3);
VirtualDub.video.SetSmartRendering(0);
VirtualDub.video.SetPreserveEmptyFrames(0);
VirtualDub.video.SetFrameRate2(25,1,1);
VirtualDub.video.SetIVTC(0, 0, 0, 0);
VirtualDub.video.SetCompression();
VirtualDub.video.filters.Clear();
VirtualDub.audio.filters.Clear();
The first line imports the wav-converted audio track.
Can I set an equivalent pipe in ffmpeg (possibly, using FLAC - not wav)? SetFrameRate2 is maybe the key, here.

Extract audio from Transport Stream and preserve length

I'm using ffmpeg to extract audio from MPEG Transport Stream file recorded by DVB-S card. The command:
ffmpeg -i video.ts -vn audio.wav
The source file seems to be corrupted. I noticed the corruption happens from time to time, especially for videos longer than 1 hour. I've got errors like these:
[mp2 # 0x1bb5500] Header missing
Error while decoding stream #0:1
[mpegts # 0x17eaf40] Continuity check failed for pid 5261 expected 2 got 6
The problem is that the resulting audio.wav is shorter than the source video (40m33s and 40m59s accordingly). I'm looking for the way to preserve the original length in the resulting audio file.
I tried the recent ffmpeg under Windows and avconv under Ubuntu, output format was MP3 and WAV. For every case I've got the same results.
I didn't find whether it's possible to do it with ffmpeg however I found ProjectX - a tool which tries to fix the broken TS stream. Website: http://project-x.sourceforge.net/
With:
java -jar ProjectX.jar -demux my_video.ts
the stream is demuxed into audio and video files which are guaranteed to have the same length. I simply mux them back using ffmpeg.

SoX: What is the correct method to trim, pipe and concatenate audio files together?

I use the following code to trim, pipe and concatenate my audio files.
sox "|sox audio.wav -p trim 0.000 =15.000" "|sox audio.wav -p trim 15.000" concatenated.wav
One would expect that concatenated.wav will sound identical compared to a.wav.
However, when both files are played simultaneously together, there is a distinct audio shift on concatenated.wav.
Normally this error is acceptable as it is in the milliseconds range. However, as the number of pipe increases (say more than 100), the amount of audio shift increases substantially.
What is the correct method to trim, pipe and concatenate audio files using SoX to prevent this error?
Edit 1: Samples was used instead of milliseconds. Still met the same problem.
The following code was used:
sox "|sox audio.wav -p trim 0s =661500s" "|sox audio.wav -p trim 661500s" concatenated.wav
Wave file sample rate is 44100hz. Sample size is 16 bit.
SoX 14-4-2 was used.
The problem is that sox may lose a few samples at the cut point of the trim command.
I had a similar problem and solved it by cutting not by milliseconds, but by samples, which of course depend on the sample rate.
If your cutpoints are multiples of the used sample rate, you will no longer lose samples and the combined parts will have the exact same length as the original.

Resources