11

I have a set of MP3 files that I would like to remove the last 4 seconds. I know that if I know the time duration of each file I can do:

ffmpeg -t ${1} -i inputfilename -acodec copy -vcodec copy outputfilename

Where $1 is the duration of the file minus the 4 seconds.

I'd really like something that would just chop the last 4 seconds off regardless of the length of the file. A "stop 4 seconds before the EOF".

Note: I struggled to figure this command line out, if there's an easier version, I love to see it.

llogan
  • 11,518
  • 43
  • 54
LarryM
  • 530
  • 5
  • 18
  • 1
    If these are simple audio mp3s FFmpeg might be overkill for your needs? Sox will do the job fine: `sox input.mp3 output.mp3 trim 0 -4`. I can write this up if you are interested in using Sox in this way... – andrew.46 Jul 20 '21 at 09:04
  • This looks fine, but... I did "sudo apt install sox" and when I run the command I get "sox FAIL formats: no handler for file extension 'mp3'" ? – LarryM Jul 20 '21 at 12:17
  • Okay, did: sudo apt-get install libsox-fmt-mp3 and now trimming the end works fine - thanks! But I'd also like to trim 2 seconds from the start odf some other files. I tried: sox input.mp3 output.mp3 trim =2 (and other variations) but that doesn't seem to do it. Suggestions? – LarryM Jul 20 '21 at 14:05

3 Answers3

9

Sometimes when dealing with audio files, rather than audio plus video, a more nuanced application than FFmpeg is SoX. Install a fully featured SoX on Ubuntu as follows:

sudo apt-get install sox libsox-fmt-all

And to trim 4 seconds from the end of your mp3 file the following very simple command is required:

sox input.mp3 output.mp3 trim 0 -4

In this example '0' is the starting position at the beginning of the file while '-4' establishes the end position of the required segment: 4 seconds from the end.

Multiple variations on this, with multiple positions and saved segments, are possible. For example, as you have mentioned in the comments, if you only wanted to remove 2 seconds at the beginning of your file the command line would be:

sox input.mp3 output.mp3 trim 2

In this example no end position is required. The SoX man pages contain many more examples of the trim command if you want more complex usage...

andrew.46
  • 37,085
  • 25
  • 149
  • 228
  • 1
    Perfect, thank you! – LarryM Jul 21 '21 at 11:37
  • 1
    @LarryM Great news that it has worked for you :). Can you 'Accept' the answer by clicking on the check or tick mark near the answer and this way future readers of this question will know that this is the best answer. And have a great day! – andrew.46 Jul 22 '21 at 05:04
5

Adapted from Cut video with ffmpeg:

ffmpeg -i input.mp3 -ss 4 -i input.mp3 -c copy -map 0:a -map 1:a -shortest -f nut - | ffmpeg -y -f nut -i - -c copy -map 0:0 output.mp3

What this does is uses the same input twice in a roundabout method to trim without needing to know duration and without re-encoding.

  1. The second input has 4 seconds cut off from the beginning.
  2. The -shortest option uses the shortest input duration to determine duration of the outputs. This results in cutting off the last 4 seconds from the first input to match the duration of the truncated second input.
  3. Because both streams are needed for -shortest to work they are piped to another ffmpeg to remove the second input.
llogan
  • 11,518
  • 43
  • 54
2

You can use ffprobe that should come with ffmpeg to get the duration.

dur=$(($(ffprobe -loglevel error -show_entries format=duration -of default=nk=1:nw=1 inputfilename | xargs printf %.0f)-4))
ffmpeg -t ${dur} -i inputfilename -c copy outputfilename

The first line uses ffprobe to get the duration minus 4 seconds then puts it in a var called dur.

I have also used xargs to round the number because bash only accepts whole numbers when doing math operations.

You can use bc if you need more accuracy.

dur=$(ffprobe -loglevel error -show_entries format=duration -of default=nk=1:nw=1 inputfilename)
dur=$(bc <<< ${dur}-4)
ffmpeg -t ${dur} -i inputfilename -c copy outputfilename
Aenfa
  • 408
  • 2
  • 6
  • way overkill solution – qwr Jul 20 '21 at 16:12
  • 1
    No need for `sed` as the duration can be retrieved directly with `ffprobe` alone. See [How do I add a 1 second fade out effect to the end of a video with ffmpeg?](https://askubuntu.com/a/1128909/) for a similar approach. `-acodec copy -vcodec copy` can be shortened to `-c copy`. – llogan Jul 20 '21 at 16:14