6

I have a bunch of .mp3 files that I would like to modify so that they start with a voice saying the file name. The easiest way to do this (or so I thought), would be something like the following:

for file in ./*.mp3; do
    BASE="$(basename "$file" .mp3)"
    mv $file $BASE-bak.mp3
    say "[[volm 0.4]] $BASE" -o $BASE-pre.aiff
    ffmpeg -i $BASE-pre.aiff -f mp3 -acodec libmp3lame -ab 192000 -ar 44100 $BASE-pre.mp3
    rm $BASE-pre.aiff
    mp3cat -o $file $BASE-pre.mp3 $BASE-bak.mp3
done

This almost works, but the resulting mp3 file is broken (it is the right length, but silent, and always stops playing after the length of time taken (I assume) to say the file name (roughly 2 seconds). Everything seems to break at the mp3cat step. However, using ffmpeg or mp3wrap or other things don't seem to work either, and my guess is that it's something to do with the file produced by say not having the right amount of streams (whatever that might mean).

Suggestions on how to fix this, or how to do this an entirely different way?

  • Does the $BASE-pre.aiff file itself work? – nohillside Oct 16 '19 at 6:20
  • As a side remark: you should things like $BASE-pre.aiff in " " to protect any space characters etc. in the filenames. – nohillside Oct 16 '19 at 6:21
  • @nohillside yes, it works fine! and ah ok, I was never sure when to use “”s, so will fix that (although it seems to deal with spaces fine at the moment) – Tim Oct 16 '19 at 11:22
  • is this question better suited to the superuser stackexchange? – Tim Oct 16 '19 at 19:52
  • 1
    Guess: You may have to encode $BASE-pre.mp3 in the same way as the mp3 file you are appending (bit rate, stereo, etc.). Check which parameters they use, and if they are all the same parameters. – dirkt Oct 22 '19 at 13:53
2
+50

Modified your script to use ffmpeg. As always, backup your files before running the scripts to avoid losing data.

Option 1

Slower, will re-encode the files, but preserves metadata:

for file in ./*.mp3; do
    BASE="$(basename "$file" .mp3)"
    mv "${file}" "${BASE}-bak.mp3"
    say "[[volm 0.4]] ${BASE}" -o "${BASE}-pre.aiff"
    ffmpeg -i "${BASE}-pre.aiff" -f mp3 -acodec libmp3lame -ab 192000 -ar 44100 "${BASE}-pre.mp3"
    rm "${BASE}-pre.aiff"
    ffmpeg -i "${BASE}-pre.mp3" -i "${BASE}-bak.mp3" -filter_complex [0:a][1:a]concat=n=2:v=0:a=1 -map_metadata 1 "${file}"
    rm "${BASE}-pre.mp3"
done

Option 2:

Fast, no re-encoding, metadata will be lost:

for file in ./*.mp3; do
    BASE="$(basename "$file" .mp3)"
    mv "${file}" "${BASE}-bak.mp3"
    say "[[volm 0.4]] ${BASE}" -o "${BASE}-pre.aiff"
    ffmpeg -i "${BASE}-pre.aiff" -f mp3 -acodec libmp3lame -ab 192000 -ar 44100 "${BASE}-pre.mp3"
    rm "${BASE}-pre.aiff"
    echo "file '${BASE}-pre.mp3'" >temp
    echo "file '${BASE}-bak.mp3'" >>temp
    ffmpeg -f concat -safe 0 -i temp "${file}"
    rm "${BASE}-pre.mp3"
    rm temp
done

Either way the resulting files seem to work fine using QuickTime, and it plays the entire file properly.

| improve this answer | |
  • this works perfectly, thank you! – Tim Oct 27 '19 at 16:01
2

Try this: Convert the target .mp3 also into the same format you're converting. Rewriting your steps with a few modifications and be-careful's:

mkdir -p backup/
mkdir -p working/
for file in ./*.mp3; do
    BASE="$(basename "$file" .mp3)"
    say "[[volm 0.4]] $BASE" -o "${BASE}-pre.aiff"
    ffmpeg -i "${BASE}-pre.aiff" -f mp3 -acodec libmp3lame -ab 192000 -ar 44100 "${BASE}-pre.mp3"
    ffmpeg -i "$file" -f mp3 -acodec libmp3lame -ab 192000 -ar 44100 "${BASE}-bak.mp3"
    rm "${BASE}-pre.aiff"
    mv "$file" backup/
    mp3cat -o "$file" "${BASE}-pre.mp3" "${BASE}-bak.mp3"
    mv "${BASE}-pre.mp3" working/
    mv "${BASE}-bak.mp3" working/
done
| improve this answer | |
  • this almost works! the resulting files stop playing after about a second and then won't play at any point after that if I use Quicktime, but in VLC they'll happily play all the way through. However, only about a second of the file name is read before the original mp3 starts playing, cutting it off... – Tim Oct 23 '19 at 20:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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