How to Sync a Music Collection to an iPod on Linux

This tutorial describes a complete workflow for transferring a CD collection to an iPod using Xubuntu/Linux:

Audio CD
   ↓
Asunder CD Ripper
   ↓
FLAC lossless files
   ↓
MusicBrainz Picard
   ↓
Metadata + album artwork
   ↓
FFmpeg
   ↓
MP3 files for the iPod
   ↓
gtkpod
   ↓
iPod

The main idea is to keep the original FLAC files as your high-quality music archive and create a separate MP3 library for the iPod.


The tools

Asunder CD Ripper

Asunder is used to rip audio CDs. In this workflow, the CDs are ripped to FLAC, a lossless audio format.

Website: http://littlesvr.ca/asunder/

The original files remain available as a high-quality archive.

MusicBrainz Picard

Website: https://picard.musicbrainz.org/

MusicBrainz Picard identifies the music and adds metadata such as:

  • Artist
  • Album
  • Track title
  • Track number
  • Disc number
  • Album artwork

After this step, the FLAC collection is properly tagged and organized.

FFmpeg

Website: https://www.ffmpeg.org/

FFmpeg converts the FLAC files into MP3 files suitable for the iPod.

The conversion script below preserves the metadata and embedded artwork.

gtkpod

Website: https://github.com/trinitonesounds/gtkpod

gtkpod is used to manage and synchronize music with the iPod from Linux.


1. Organize your FLAC collection

In my case, the original collection is organized like this:

/media/username/Nextcloud/MUSIC CD COLLECTION/
├── Alice In Chains - Alice In Chains/
│   ├── 01 - Alice In Chains - Grind.flac
│   ├── 02 - Alice In Chains - Brush Away.flac
│   └── ...
├── Alice in Chains - Dirt/
│   ├── 01 - Alice in Chains - Them Bones.flac
│   └── ...
└── ...

The conversion script will recreate the same folder structure in the MP3 destination:

/home/username/Music/
├── Alice In Chains - Alice In Chains/
│   ├── 01 - Alice In Chains - Grind.mp3
│   └── ...
├── Alice in Chains - Dirt/
│   ├── 01 - Alice in Chains - Them Bones.mp3
│   └── ...
└── ...

The original FLAC files are never modified.


2. Install FFmpeg

On Xubuntu:

sudo apt update
sudo apt install ffmpeg

Verify the installation:

ffmpeg -version

3. Choose the MP3 bitrate

The script uses a configurable bitrate:

BITRATE="256k"

Common choices are:

192k  → smaller files
256k  → good balance between quality and size
320k  → highest common MP3 bitrate

For my iPod, I chose 256 kbps as a good balance between quality and storage space.

You can change this value without modifying the rest of the script.


4. Create the conversion script

Create a new file:

nano convert-music.sh

Paste the following:

#!/usr/bin/env bash

set -u

# ============================================================
# CONFIGURATION
# ============================================================

# Folder containing the original FLAC collection
SOURCE_DIR="/media/username/MUSIC CD COLLECTION"

# Folder where converted MP3 files will be stored
DEST_DIR="/home/username/Music"

# MP3 bitrate
#
# Examples:
#
#   192k = smaller files
#   256k = good balance
#   320k = highest common MP3 bitrate
#
BITRATE="256k"

# Log file
LOG_FILE="$DEST_DIR/convert-music.log"


# ============================================================
# PREPARATION
# ============================================================

mkdir -p "$DEST_DIR"

# Add a header to the log for this execution
{
    echo
    echo "============================================================"
    echo "Conversion started: $(date)"
    echo "Source: $SOURCE_DIR"
    echo "Destination: $DEST_DIR"
    echo "Bitrate: $BITRATE"
    echo "============================================================"
} >> "$LOG_FILE"


# ============================================================
# COUNTERS
# ============================================================

converted=0
skipped=0
failed=0


# ============================================================
# CONVERSION
# ============================================================

while IFS= read -r -d '' input_file; do

    # Get the path relative to SOURCE_DIR
    relative_path="${input_file#"$SOURCE_DIR"/}"

    # Replace .flac with .mp3
    output_file="$DEST_DIR/${relative_path%.*}.mp3"

    # Create the destination directory
    mkdir -p "$(dirname "$output_file")"

    # Skip files that already exist
    if [[ -f "$output_file" ]]; then

        echo "SKIPPED: $output_file"
        echo "SKIPPED: $output_file" >> "$LOG_FILE"

        ((skipped++))

        continue
    fi

    echo
    echo "Converting:"
    echo "  $input_file"
    echo "→ $output_file"

    echo "CONVERTING: $input_file" >> "$LOG_FILE"

    if ffmpeg -nostdin -y \
        -i "$input_file" \
        -map 0:a:0 \
        -map 0:v:0? \
        -map_metadata 0 \
        -c:a libmp3lame \
        -b:a "$BITRATE" \
        -ac 2 \
        -ar 44100 \
        -c:v mjpeg \
        -q:v 3 \
        -id3v2_version 3 \
        "$output_file" >> "$LOG_FILE" 2>&1
    then

        echo "SUCCESS: $output_file"
        echo "SUCCESS: $output_file" >> "$LOG_FILE"

        ((converted++))

    else

        echo "FAILED: $input_file"
        echo "FAILED: $input_file" >> "$LOG_FILE"

        # Remove an incomplete output file, if one was created
        rm -f "$output_file"

        ((failed++))

    fi

done < <(
    find "$SOURCE_DIR" \
        -type f \
        -iname "*.flac" \
        -print0
)


# ============================================================
# SUMMARY
# ============================================================

echo
echo "============================================================"
echo "Conversion finished: $(date)"
echo "Converted: $converted"
echo "Skipped:   $skipped"
echo "Failed:    $failed"
echo "Log file:  $LOG_FILE"
echo "============================================================"

{
    echo
    echo "SUMMARY"
    echo "-------"
    echo "Converted: $converted"
    echo "Skipped:   $skipped"
    echo "Failed:    $failed"
    echo "Finished:  $(date)"
    echo
} >> "$LOG_FILE"

5. Make the script executable

Run:

chmod +x convert-music.sh

Then execute it:

./convert-music.sh

The script will recursively find all .flac files and convert them.


6. Running the script again

The script is safe to run repeatedly.

If the MP3 file already exists, it is skipped:

SKIPPED: /home/username/Music/Alice in Chains - Dirt/01 - Alice in Chains - Them Bones.mp3

This is useful when adding new albums to the FLAC collection.

For example:

First execution:
    500 songs converted

Later:
    20 new FLAC files added

Second execution:
    500 existing songs skipped
    20 new songs converted

The script does not need to reconvert the entire collection.

If you want to regenerate a particular MP3, simply delete that MP3 and run the script again.


7. The conversion log

The script creates:

/home/username/Music/convert-music.log

The log contains useful information such as:

Conversion started: ...

CONVERTING: /path/to/song.flac
SUCCESS: /path/to/song.mp3

SKIPPED: /path/to/existing-song.mp3

FAILED: /path/to/problematic-song.flac

SUMMARY
-------
Converted: 25
Skipped:   450
Failed:    1

FFmpeg’s output is also written to the log, which makes it possible to investigate conversion problems later.


8. What the FFmpeg options do

The important parts of the command are:

-map 0:a:0

Selects the audio stream.

-map 0:v:0?

Selects embedded artwork if it exists.

The ? makes the artwork optional, so files without cover art can still be converted.

-map_metadata 0

Copies metadata from the original FLAC file.

-c:a libmp3lame

Uses the LAME MP3 encoder.

-b:a "$BITRATE"

Uses the bitrate configured at the top of the script.

-c:v mjpeg

Converts embedded artwork to JPEG.

-id3v2_version 3

Uses ID3v2.3 metadata, which is a good compatibility choice for older devices and software.

-nostdin

Prevents FFmpeg from reading from the script’s input stream. This is important when processing a list of files with Bash.


9. Synchronize the MP3 files with gtkpod

After the conversion finishes, open gtkpod and add the MP3 files from:

/home/username/Music

The metadata should be available in the MP3 files, including:

  • Artist
  • Album
  • Track title
  • Track number
  • Album artwork

gtkpod then updates the iPod’s music database and artwork database.

For older iPods, embedded artwork alone is not always enough. The artwork also needs to be processed by gtkpod/libgpod and added to the iPod’s artwork database.

This is why the final step is important:

FLAC with metadata and artwork
        ↓
FFmpeg conversion
        ↓
MP3 with metadata and artwork
        ↓
gtkpod
        ↓
iPod music and artwork databases
        ↓
Music and album covers on the iPod

Final result

The complete workflow is:

CD
 ↓
Asunder CD Ripper
 ↓
FLAC lossless archive
 ↓
MusicBrainz Picard
 ↓
Metadata + album artwork
 ↓
FFmpeg conversion script
 ↓
MP3 library with configurable bitrate
 ↓
gtkpod
 ↓
iPod

The most important advantage of this approach is that the FLAC files remain your original, lossless collection. The MP3 files are simply a smaller, portable copy generated specifically for the iPod.

If you later decide to use a different bitrate, you can change:

BITRATE="256k"

and regenerate the MP3 files you want.