6

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?

Jasper
  • 908
  • 8
  • 17
  • 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](http://mp3diags.sourceforge.net/145_transformations_list.html) scans and detects truncated files. If you choose so, it even repairs them. It is available for [Linux and Windows](http://sourceforge.net/projects/mp3diags/files/?source=navbar) – nixda Aug 28 '15 at 13:04

1 Answers1

2

This is the script I'm now using:

#!/bin/bash

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"
  else
    len_diff=$(( $ffmpeg_dur - $mp3_check_dur ))
    if [[ $len_diff -gt 0 ]] ; then
      echo -e "ERROR (length): $filename\t${len_diff}"
    fi
  fi

done

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.

Jasper
  • 908
  • 8
  • 17