55

I am looking for a software in Linux, that will add the album-art/cover to each of the selected files in batch-mode. The album art is a jpg/png stored in my computer. It will be awesome if it can import from internet.

Currently I have tried both Rhythmbox and Banshee. I have also tried lame and easytag, but seems they do not support batch mode. lame is not adding the properties, but overwriting. (I know lame is the only command line s/w i have used so far).

So, basically I am looking for:

<some magic s/w> --picture=<my chosen picture> Music/Artist/*.mp3

That will add the picture to the metadata of the file, permanently.

Can you suggest me any such software?

slm
  • 363,520
  • 117
  • 767
  • 871
BaRud
  • 1,599
  • 2
  • 15
  • 26

9 Answers9

41

lame

Using lame you can do this using a little scripting:

$ lame --ti /path/to/file.jpg audio.mp3

If the files are named something like this you can make a shell script to do what you want:

for i in file1.mp3 file2.mp3 file3.mp3; do
  albart=$(echo $i | sed 's/.mp3/.jpg/')
  lame --ti /path/to/$albart $i
done

You can make the above slightly more compact and eliminate the need for sed by using bash to do it by having it remove the matching suffix:

...
albart="${i%.mp3}.jpg"
...

Picard/MusicBrainz

If you want to do this on a large scale I'd suggest using Picard which is the frontend tool for using the MusicBrainz database. There is a plugin to Picard called "Cover Art Downloader", which can do this to batches of your collection.

The above doesn't appear to be command line driven however.

beets

Another option would be to use beets. This can be driven from the command-line and makes use of MusicBrainz database for sourcing the album art.

You can either source the album art usingFetchArt Plugin or embed it using the EmbedArt Plugin.

Other options?

Also take a look at this previously asked U&L Q&A titled: Which mp3 tagging tool for Linux?. There are several alternative tools listed in this thread.

slm
  • 363,520
  • 117
  • 767
  • 871
  • You can avoid the `sed` call with something like `albart="${i%.mp3}.jpg"`. More importantly, I just tested your lame command and got `lame: unrecognized option -i`... – evilsoup Jul 30 '13 at 23:09
  • @evilsoup - thanks, the switch was missing a dash. Should be `--ti ..`. – slm Jul 30 '13 at 23:15
  • @evilsoup - also added your feedback on not using `sed`. Thanks! – slm Jul 30 '13 at 23:24
  • Is it possible to remove the cover art with `lame`, too? – Exeleration-G Dec 09 '13 at 10:09
  • 12
    @Exeleration-G - no I wouldn't recommend using `lame` since it's actually an encoder. There are other tools for just manipulating the id3 tags of an mp3. You can use `id3v2 -r "APIC" *.mp3` or `eyeD3 --remove-all-images *.mp3` to remove any attached images. – slm Dec 09 '13 at 13:34
  • Just a minor correction: it should be `eyeD3 --remove-images *.mp3` – Exeleration-G Dec 09 '13 at 20:56
  • @Exeleration-G - in my version it's "--remove-all-images Remove all images from the tag". ver. 0.7.3-final. – slm Dec 09 '13 at 21:26
  • @sim: This must be something that changed with the last versions. I'm using `eyeD3 0.6.18` on Ubuntu 13.10. – Exeleration-G Dec 09 '13 at 21:43
  • @Exeleration-G - yeah no biggie, switches change, always consult a tool's usage: `eye3d --help` or man page. – slm Dec 10 '13 at 02:09
  • 2
    I do not recommend this solution because it deletes the other id3 tags. The solution with `ffmpeg` is better. – antoyo Dec 02 '17 at 15:58
  • 2
    FYI my version 3.99 does not have a "--ti" option (debian buster) - eyeD3 seems to be a good alternative. – Benjamin Peter Oct 25 '19 at 20:07
  • 1
    I do not think that this should recommend using `lame --ti`. AFAICT that will *lossily re-encode* the MP3 file, which isn't clear at all from this answer. – jamesdlin Oct 21 '22 at 07:58
  • 1
    Fixed this answer, so the audio quality is not reduced: https://unix.stackexchange.com/a/752036/115743 – digitalextremist Jul 21 '23 at 01:21
27

One solution would be to use ffmpeg:

ffmpeg -i input.mp3 -i cover.jpg -map_metadata 0 -map 0 -map 1 output.mp3

You can put this in a for loop to do every MP3 in a directory:

for f in ./*.mp3; do ffmpeg -i "$f" -i cover.jpg -map_metadata 0 -map 0 -map 1 out-"${f#./}"; done

This will create a separate output file (so if you have a file called foo.mp3, you will end up with both foo.mp3 and out-foo.mp3); this is because ffmpeg cannot write over its input. You can fix this with something like:

for f in ./*.mp3; do \
ffmpeg -i "$f" -i cover.jpg -map_metadata 0 -map 0 -map 1 out-"${f#./}" \
&& mv out-"${f#./}" "$f"; done

Using ffmpeg for this problem is a little bit like using a cruise missile to crack a nut. More specialised metadata-manipulating tools will certainly be able to do this in a cleaner, shorter command.

evilsoup
  • 6,727
  • 3
  • 33
  • 40
  • 17
    The ffmpeg command shown here will encode the audio. If you're converting from another format, that's fine, but if you just want to add art to an existing mp3 without re-encoding it, add `-acodec copy` after the `-map 1`. – jsd Mar 24 '15 at 18:39
  • This isn't working for me, any particular reason? I only get the mp3 file but no thumbnail. @jsd – Chef Pharaoh Aug 14 '16 at 22:13
  • Sorry @ChefPharaoh I don't know why it isn't working for you. I just tried doing wav->mp3 while adding art, and just adding art to an existing mp3 with those ffmpeg commands shown above. Both times it worked fine. – jsd Aug 15 '16 at 16:51
  • @evilsoup I'm not sure if I am doing something super evil or wrong, but I am able to modify my mp3 files in place using process substitution. Kinda simplifies this script and it seems to be super fast. – rien333 Oct 30 '18 at 12:26
  • Worked like a treat, and I also found ffmpeg to be slightly faster than lame :) – Tina Mar 05 '19 at 01:11
  • ffmpeg can´t set a cover – womenlover Apr 18 '22 at 09:41
  • Yes, `ffmpeg` can set a cover: confirmed with the command line from @evilsoup and the update from @jsd: `ffmpeg -i in.mp3 -i cover.jpg -map_metadata 0 -map 0 -map 1 -acodec copy out.mp3` – NeilG Sep 25 '22 at 03:49
20

For MP3:

eyeD3 --add-image="cover.jpg":FRONT_COVER "file.mp3"

For FLAC:

metaflac --import-picture-from="cover.jpg" "file.flac"

OGG/Vorbis seems to be more complicated.

Raphael
  • 2,035
  • 1
  • 21
  • 34
8

Use mid3v2 from mutagen:

mid3v2 -p <image> <mp3>

Using lame or ffmpeg recodes the MP3 instead of only adding the image as meta-blob. And UI is not commandline.

motzmann
  • 186
  • 1
  • 7
5

You can use FancyAudio gem for this. It can add album art to mp3 files. Documentation is available here.

features

  1. add album art to single mp3 file
  2. add album art to multiple mp3 files.

Below screen shot shows the output of fancy_audio when run in a folder containing an image and multiple mp3 files

enter image description here

Below screen shot shows the output of fancy_audio when run in a folder containing mp3 and image files

This image shows the output of fancy_audio when run in a folder containing mp3 and image files

Ajit Singh
  • 151
  • 1
  • 4
  • This is easy, and works faster than `lame` when adding the same image to multiple mp3 files. You don't need to know Ruby ;) - this is a standalone script. – Tomasz Gandor Jan 29 '17 at 23:44
3

eyeD3 does not work with Unicode. If any non-ascii characters are in the .mp3 file name (or even in just an ancestor directory name, such as the Album directory), then it aborts. LTA.

So you are out of luck if the Album or Song title is not written in English!

For example:

cp yoursong.mp3 /tmp/Странджанска.mp3
eyeD3 --add-image folder.jpg:FRONT_COVER Странджанска.mp3

Apparently eyeD3 wants to put the full path of the .mp3 file inside the .mp3 file and can't handle non-ascii characters.

Uncaught exception: 'ascii' codec can't encode characters in position 5-16: ordinal not in range(128)
eyed3:ERROR: 'ascii' codec can't encode characters in position 5-16: ordinal not in range(128)
Traceback 
...(long traceback omitted)...
Jim Avera
  • 41
  • 1
  • 1
    Why was this useful and helpful additional information downvoted? – Lizardx Jan 15 '20 at 20:00
  • eyed3 version 0.8.10 in Ubuntu 20.04 seems to work fine with UTF8 file names. I just used it on 21 files named "...Ungarische Tänze...mp3". The "ä" in the file name was not a problem. And I also copied a file to the cyrillic name in your example, and it worked fine with that too. My system is configured to use UTF8. – mivk Jul 17 '21 at 15:07
1

OP states that he would prefer if the cover is downloaded from the web, and I just wrote a pretty okay script for that using eye3D and sacad, both installable from pip. eye3D is very useful for this purpose as it doesn't seem to re-encode audio and using the --to-v2.4 flag handles any mp3 files, no matter the type of id3 tag. The script should be launched from the directory that contains the mp3 files. It can be run with no arguments, guessing the artist and album name from the id3 tags, or with manual names as arguments, e.g. embedart "pink floyd" "dark side of the moon". It's written for the fish shell, but should easily be portable to bash if you change all the set commands to bash variable assigments.

function embedart
    if echo $argv | grep -q -e '-h'
       echo 'embedart "[Artist]" "[Album]"'
       return
    end

    if test $argv[1]
        set artist $argv[1]
        set album $argv[2]
    else
        set artist (eyed3 (ls *mp3 | head -1) | ggrep -oP "artist.*: \K.*" | head -1)
        if not test $artist
            echo "No artist found!"
            return
        end
        set album (eyed3 (ls *mp3 | head -1) | ggrep -oP "album.*: \K.*" | head -1)
        if not test $album
            echo "No album found!"
            return
        end
    end

    sacad $artist $album 350 cover.jpg -v warning 2> /dev/null > /dev/null
    eyeD3 --to-v2.4 --add-image "cover.jpg:FRONT_COVER" *mp3 -Q 2> /dev/null > /dev/null

    rm cover.jpg
    echo "Done!"
end
rien333
  • 613
  • 4
  • 15
0

For convenient.

For /album/*.mp3

for f in */*.mp3
do 
    if [[ -e ${f%/*.mp3}/cover.jpg ]]; then
    ffmpeg -i "$f" -i ${f%/*.mp3}/cover.jpg -map_metadata 0 -map 0 -map 1 out-"${f#*/}" && mv out-"${f#*/}" "$f"
    else
    echo "=============================" 
    echo ${f%/*.mp3}/ #Find a folder which doesn't have cover.jpg
    fi
done

For "/album/cd 1/*.mp3"

for f in */*/*.mp3
do 
    if [[ -e ${f%/*.mp3}/cover.jpg ]]; then
    ffmpeg -i "$f" -i ${f%/*.mp3}/cover.jpg -map_metadata 0 -map 0 -map 1 out-"${f#*/*/}" && mv out-"${f#*/*/}" "$f"
    echo "=============================" 
    echo ${f%/*.mp3}/ #Find a folder which doesn't have cover.jpg
    fi
done

thanks to https://unix.stackexchange.com/a/84956/401765

-1

This is amending the Accepted Answer which will reduce the quality of high-fidelity recordings.


Example of how to keep maximum audio quality, versus be chopped and clobbered:

lame --preset insane -b 320 -h -V 0 --ti <image> <out>.mp3
  • Recoding to CBR 320 is clearly inappropriate for most existing MP3 streams. Much better not to touch the audio data at all, as shown in the better answers. – Toby Speight Jul 21 '23 at 12:02
  • All the `lame` answers reduce audio to 128. The purpose of the answer was to amend that already accepted answer, which degrades the audio. – digitalextremist Jul 22 '23 at 02:35