Claude
Skills
Sign in
Back

Cover Art Embedding

Included with Lifetime
$97 forever

Patterns for finding, processing, and embedding cover artwork into media files

media-curator

What this skill does


# Cover Art Embedding Skill

Concrete patterns for finding high-quality cover artwork, processing it for optimal size and format, and embedding it into audio and video files.

## Artwork Sources

### MusicBrainz Cover Art Archive (Primary)

MusicBrainz Cover Art Archive (CAA) is the authoritative source for album artwork.

**Get Front Cover by Release MBID**:
```bash
# Download front cover for a release
curl -s "https://coverartarchive.org/release/{mbid}/front" -o cover.jpg

# Example with real MBID
curl -s "https://coverartarchive.org/release/5c004fe3-6e96-3f43-9a85-16e5be8805fa/front" -o blue-cover.jpg
```

**Check if Cover Exists**:
```bash
# HEAD request to check without downloading
if curl -s -I "https://coverartarchive.org/release/${mbid}/front" | grep -q "200 OK"; then
  echo "Cover available"
else
  echo "No cover found"
fi
```

**Get All Available Images**:
```bash
# Get metadata for all images
curl -s "https://coverartarchive.org/release/${mbid}" | jq .

# Extract URLs for all front covers
curl -s "https://coverartarchive.org/release/${mbid}" | \
  jq -r '.images[] | select(.front == true) | .image'

# Download highest resolution front cover
url=$(curl -s "https://coverartarchive.org/release/${mbid}" | \
  jq -r '.images[] | select(.front == true) | .image' | head -1)
curl -s "$url" -o cover.jpg
```

### fanart.tv API

fanart.tv provides high-quality artist images, album covers, and logos.

**Get Artist Images**:
```bash
# Requires API key from https://fanart.tv/get-an-api-key/
FANART_API_KEY="your-api-key"

# Get all artist artwork
curl -s "https://webservice.fanart.tv/v3/music/${mbid}?api_key=${FANART_API_KEY}"

# Extract album cover URLs
curl -s "https://webservice.fanart.tv/v3/music/${mbid}?api_key=${FANART_API_KEY}" | \
  jq -r '.albums."'"$album_mbid"'".albumcover[0].url'

# Extract artist background
curl -s "https://webservice.fanart.tv/v3/music/${mbid}?api_key=${FANART_API_KEY}" | \
  jq -r '.artistbackground[0].url'

# Extract artist logo
curl -s "https://webservice.fanart.tv/v3/music/${mbid}?api_key=${FANART_API_KEY}" | \
  jq -r '.hdmusiclogo[0].url'
```

**Download Artwork**:
```bash
# Download album cover
url=$(curl -s "https://webservice.fanart.tv/v3/music/${mbid}?api_key=${FANART_API_KEY}" | \
  jq -r '.albums."'"$album_mbid"'".albumcover[0].url')
curl -s "$url" -o cover.jpg
```

### Video Thumbnail Extraction

Extract cover artwork from video frames.

**Using yt-dlp** (if video was downloaded with thumbnail):
```bash
# Download video with thumbnail
yt-dlp --write-thumbnail --convert-thumbnails jpg "https://youtube.com/watch?v=..."

# Result: video.jpg alongside video.mp4
```

**Using ffmpeg** (extract from video):
```bash
# Extract single frame at specific time
ffmpeg -i input.mp4 -ss 00:00:10 -frames:v 1 -q:v 2 thumbnail.jpg

# Extract I-frame (best quality)
ffmpeg -i input.mp4 -vf "select=eq(pict_type\,I)" -frames:v 1 -q:v 2 thumbnail.jpg

# Extract frame at 25% into video
duration=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 input.mp4)
timestamp=$(echo "$duration * 0.25" | bc)
ffmpeg -i input.mp4 -ss "$timestamp" -frames:v 1 -q:v 2 thumbnail.jpg

# Extract highest quality frame from first minute
ffmpeg -i input.mp4 -t 60 -vf "select=eq(pict_type\,I)" -vsync vfr -q:v 1 frames-%03d.jpg
# Then manually select best frame
```

### Local Artwork Files

Scan for existing artwork in standard locations:

```bash
# Check for common filenames in album directory
for name in cover.jpg Cover.jpg folder.jpg Folder.jpg albumart.jpg AlbumArt.jpg; do
  if [ -f "$name" ]; then
    echo "Found: $name"
    break
  fi
done

# Search parent directory
if [ -f "../cover.jpg" ]; then
  cp "../cover.jpg" .
fi

# Find largest image file (likely the cover)
largest=$(find . -maxdepth 1 -type f \( -iname "*.jpg" -o -iname "*.png" \) -exec ls -s {} \; | \
  sort -rn | head -1 | awk '{print $2}')
echo "Largest image: $largest"
```

## Image Processing

### Resize for Mobile Optimization

Reduce image size for faster loading and smaller file sizes:

```bash
# Install ImageMagick
brew install imagemagick  # macOS
sudo apt install imagemagick  # Debian/Ubuntu

# Resize to 1200x1200 max (preserves aspect ratio)
convert input.jpg -resize 1200x1200 output.jpg

# Resize and optimize quality (85% JPEG quality)
convert input.jpg -resize 1200x1200 -quality 85 output.jpg

# Create thumbnail (300x300)
convert input.jpg -resize 300x300 thumbnail.jpg

# Batch resize all images in directory
for img in *.jpg; do
  convert "$img" -resize 1200x1200 -quality 85 "${img%.jpg}-resized.jpg"
done
```

### Format Conversion

Convert between image formats:

```bash
# PNG to JPEG
convert input.png output.jpg

# WebP to JPEG
convert input.webp output.jpg

# JPEG to PNG (lossless)
convert input.jpg output.png

# Batch convert all PNG to JPEG
for img in *.png; do
  convert "$img" "${img%.png}.jpg"
done
```

### Crop to Square

Crop non-square images to square aspect ratio:

```bash
# Center crop to square
convert input.jpg -gravity center -crop 1:1 +repage output.jpg

# Crop from top-left
convert input.jpg -crop 1200x1200+0+0 +repage output.jpg

# Smart crop (removes boring edges)
convert input.jpg -define trim:percent-background=0% -trim +repage -resize 1200x1200 output.jpg
```

### Remove Metadata (Privacy)

Strip EXIF data before embedding:

```bash
# Remove all metadata
convert input.jpg -strip output.jpg

# Or use exiftool
exiftool -all= input.jpg

# Batch strip metadata
for img in *.jpg; do
  convert "$img" -strip "${img%.jpg}-clean.jpg"
done
```

## Embedding Artwork

### Opus Files (opustags)

```bash
# Embed cover art from JPEG file
opustags input.opus --set-cover cover.jpg -o output.opus

# In-place embedding
opustags -i input.opus --set-cover cover.jpg

# Verify embedding
opustags input.opus | grep -i picture
```

### MP4 Files (ffmpeg)

```bash
# Embed cover as attached picture
ffmpeg -i input.mp4 -i cover.jpg \
  -map 0 -map 1 \
  -c copy \
  -disposition:v:1 attached_pic \
  output.mp4

# Embed with metadata
ffmpeg -i input.mp4 -i cover.jpg \
  -map 0 -map 1 \
  -c copy \
  -disposition:v:1 attached_pic \
  -metadata:s:v:1 title="Album cover" \
  -metadata:s:v:1 comment="Cover (front)" \
  output.mp4

# Verify embedding
ffprobe -v error -select_streams v -show_entries stream=codec_name,codec_type,disposition input.mp4
```

### MP3 Files (ffmpeg)

```bash
# Embed cover with ID3v2.3
ffmpeg -i input.mp3 -i cover.jpg \
  -map 0 -map 1 \
  -c copy \
  -id3v2_version 3 \
  -metadata:s:v title="Album cover" \
  -metadata:s:v comment="Cover (front)" \
  output.mp3

# Verify embedding
ffmpeg -i input.mp3 -an -vcodec copy test-extracted-cover.jpg
```

### FLAC Files (ffmpeg)

```bash
# Embed cover into FLAC
ffmpeg -i input.flac -i cover.jpg \
  -map 0 -map 1 \
  -c copy \
  -disposition:v:0 attached_pic \
  output.flac

# Using metaflac (alternative)
metaflac --import-picture-from=cover.jpg input.flac
```

## Batch Embedding

### Embed Same Cover into All Files

```bash
# Opus files in directory
for file in *.opus; do
  opustags -i "$file" --set-cover cover.jpg
  echo "Embedded: $file"
done

# MP3 files in directory
for file in *.mp3; do
  ffmpeg -i "$file" -i cover.jpg \
    -map 0 -map 1 -c copy \
    -id3v2_version 3 \
    -metadata:s:v title="Album cover" \
    "${file%.mp3}-covered.mp3"
  mv "${file%.mp3}-covered.mp3" "$file"
done
```

### Embed Different Covers per Album

```bash
# Process album directories
for album_dir in */; do
  # Find cover in album directory
  cover=$(find "$album_dir" -maxdepth 1 -iname "cover.jpg" | head -1)

  if [ -n "$cover" ]; then
    # Embed into all Opus files in this album
    for file in "$album_dir"/*.opus; do
      opustags -i "$file" --set-cover "$cover"
    done
    echo "Processed: $album_dir"
  else
    echo "No cover found: $album_dir"
  fi
done
```

### Download and Embed from MusicBrainz

```bash
#!/bin/bash
# Process all Opus files, download covers, embed

for file in *.opus; do
  # Ex

Related in media-curator