I recently had a hard disk failure and could not rescue all my music files. Since I didn't have enough storage available to do a full backup of the disk, I tried to cp as many tracks as possible, but now I am left with some files that end prematurely.

I already found this answer to find out "the song length" and this tool that does the same. For one broken file, I get this output:

ffmpeg -i broken.mp3 2>&1 | grep Duration
  Duration: 00:04:18.14, start: 0.025057, bitrate: 92 kb/s

mp3_check -a broken.mp3 2>&1| grep SONG
SONG_LENGTH         01:43.05

So ffmpeg seems to rely on some metadata (04:18 is the duration that is also displayed in my media player), while mp3_check seems to actually read the whole file. I could use this to write a script that covers mp3, but:

Is there an easier solution rather than comparing ffmpeg and mp3_check output in order to find broken files?

How would I do this with Ogg files, where no mp3_check is available?

  • I already have written a bash script for the first question, shall I include that in the question? Or does this topic fit better to Stackoverflow or Unix+Linux? – Jasper Apr 27 '14 at 18:32
  • I would encourage you to post the script as an answer anyway, and if someone has a solution, so be it. But maybe someone else will also find it helpful – a win-win situation. The question is perfectly fine here. We don't disallow scripting questions as long as they're in the context of anything a power user would do, but not exclusive to programming. And Unix/Linux questions are all on topic here too. – slhck Apr 27 '14 at 18:35
  • mp3diags scans and detects truncated files. If you choose so, it even repairs them. It is available for Linux and Windows – nixda Aug 28 '15 at 13:04

This is the script I'm now using:


echo "checking $1"

find "$1" -name "*.mp3" | while read filename; do
  echo "checking $(basename "$filename")"
  ffmpeg_dur=$(ffmpeg -i "$filename" 2>&1 | awk -F: '($1 ~ /Duration/) {printf "60*%d+%d\n", $3, $4}' | bc)
  # mp3_check_dur=$(mp3_check -a "$filename" 2>&1 | awk -F'[ :.]+' '($1 ~ /SONG_LENGTH/) {printf "60*%d+%d\n", $2, $3}' | bc )
  mp3info_dur=$(mp3info -x "$filename" 2>&1 | awk -F'[ :.]+' '($1 ~ /Length/) {printf "60*%d+%d\n", $2, $3}' | bc )

  if [[ -z $ffmpeg_dur ]] ; then  # some files are so broken that ffmpeg doesn't print a length
    echo "ERROR (ffmpeg): $filename"
    len_diff=$(( $ffmpeg_dur - $mp3_check_dur ))
    if [[ $len_diff -gt 0 ]] ; then
      echo -e "ERROR (length): $filename\t${len_diff}"


The duration reported by ffmpeg is always longer than the one of mp3_check and mp3info. There sometimes is a 1 second difference between the latter as well. mp3info is available as package for some linux distributions (Ubuntu, Arch, ...?), mp3_check has to be built from source.

  • Won't work "as is". mp3_check_dur should be replaced by mp3info_dur in $((ffmpeg_dur - mp3_check_dur)) – Andrey Regentov Jan 25 '15 at 5:25

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.