Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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?

share|improve this question
    
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 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 at 18:35

1 Answer 1

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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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