whatdoineed2do / gpod-utils

Command line utilities to manage iPods (using libgpod), incl ls, cp with auto xcode, rm, edit track meta.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

gpod utils

Command line tools using libgpod to access iPod data.

Whilst libgpod appears to be in sunset mode (last release in 2015), recent 2021 Fedora and Debian distros still provide gtkpod in their standard repos. However there are still many old iPods in the wild with a mini resurrgence of popularity for the iPod 4/5/5.5/Classic units given the relative ease in replacing batteries and swapping out their power hungry harddisks for larger capacity SD cards.

As of 2021, the last libgpod release is 0.8.3 - their docs suggests the library supports all classic iPods, iPod Touches and early iPhones. Whilst testing this codebase, only iPods were supported with iPod Touch 1G and onwards not compatible due to the signing requirement of the iTunesDB file on these devices.

Supported / Tested

Model OS Supported Comments
iPod 5G MA002LL 1.3 Yes
iPod 5.5G MA446FB 1.3 Yes
iPod Touch 1G 5.1.1 No tools appear to be success and updates the iTunesDB. Data not reflected one rescan/app. Remove appears success but next scan file exists, underlying file removed but listing on app exists. Other tracks continue to be playable
iPhone 1 MB213B 3.1.3 No tools appear to be success and updates the iTunesDB. However once a sync has been complete (cp/rm) none of the audio files are playable on the iPod app

The underlying support is provided by libgpod and the reported iPod feature matrix:

SysInfoExtended hash58 hash72 sqlite iTunesCDB
iPod 1G no no no no no
iPod 2G no no no no no
iPod 3G no no no no no
Mini 1G no no no no no
Mini 2G no no no no no
iPod 4G yes no no no no
iPod 5G yes no no no no
Nano 1G yes no no no no
Nano 2G yes no no no no
iPod Classic yes yes no no no
Nano3G yes yes no no no
Nano4G yes yes no no no
iPhoneOS 1.x yes yes no no no
iPhoneOS 2.x yes no yes no no
Nano5G yes yes yes yes yes
iPhoneOS 3.x yes no yes yes yes

mount points

Most modern Linux distros and window managers will try to automount old iPod's filesystem to a location such as /run/media/${USER}/<name of iPod>/. However this is not a given and I've seen this fail for iPhones and iPod touch even though the distros mount items through gvfs. If your iPod is not automounted, try the following to mount mkdir -p /tmp/ipod && ifuse /tmp/ipod and this to unmount fusermoumt -u /tmp/ipod when done.

gpod-ls

Simple utility that parses an iPod db and generates a json output of the internal playlists (main playlist iPod) as well as the user generated playlists - the main playlist will list most of the available track information and the other playlists will contain less verbose data. The per track object also includes checksum that is the hash value of the audio-only checksum of the file (same value as ffmpeg -hide_banner -i foo.m4a -c:a copy -bsf:a null -f hash -).

Optionally an SQLite3 db can be generated for easier investigation.

This utility can work on a mounted iPod or directly pointing the iTunesDB file - the following works on an old iPod Video 5G.

$ gpod-ls -M /run/media/ray/IPOD | tee ipod.json | jq '.'
{
  "ipod_data" {
    "playlists": {
      "items": [
        {
          "name": "iPod",
          "type": "master",
          "count": 1720,
          "smartpl": false,
          "timestamp": 1568200601,
          "tracks": [
            {
              "id": 52,
              "ipod_path": "/iPod_Control/Music/F43/SGWQ.mp3",
              "title": "foo bar",
              "artist": "Foo&Bar",
              "album": null,
              "genre": "Pop",
              "filetype": "MPEG audio file",
              "composer": "Unknown",
              "grouping": null,
              "albumartist": null,
              "sort_artist": null,
              "sort_title": null,
              "sort_album": null,
              "sort_albumartist": null,
              "sort_composer": null,
              "size": 3246551,
              "tracklen": 202840,
              "cd_nr": 0,
              "cds": 0,
              "track_nr": 0,
              "tracks": 0,
              "bitrate": 128,
              "samplerate": 44100,
              "year": 2017,
              "time_added": 1616007149,
              "time_modified": 1616872918,
              "time_played": 1616698504,
              "rating": 20,
              "playcount": 3,
              "playcount2": 0,
              "recent_playcount": 0,
              "checksum": 1503221223
            },
            ...
          ]
        },
        {
          "name": "Genius",
          "type": "playlist",
          "count": 0,
          "smartpl": false,
          "timestamp": 1616771596,
          "tracks": []
        },
        {
          "name": "Podcasts",
          "type": "podcasts",
          "count": 0,
          "smartpl": false,
          "timestamp": 1617250954,
          "tracks": []
        },
        {
          "name": "[Orphaned]",
          "type": "playlist",
          "count": 0,
          "smartpl": false,
          "timestamp": 1617251149,
          "tracks": []
        }
      ],
      "count": 4,
    },
    ...
  }
}

Directly on the db file and generating a standalone db

$ gpod-ls \
    -M /run/media/ray/IPOD/iPod_Control/iTunes/iTunesDB \
    -Q /tmp/ipod.sqlite3

The json output is not pretty printed but rather you can use other tools, such as jq to perform simple queries or to use the generated DB file.

Whilst both gtkpod and Rhythmbox provide good graphical interfaces for adding/removing music, they are less useful for data mining. Of particular use is identifying potentially duplicate tracks. Note the duplicates object - this contains 3 further objects, high, med, low which in turn contains a list of potentially duplicate tracks. The difference between these objects is the manner in which they determine matches - using basic filesize track length and then increasing to equivalence in some metadata fields. Note that it is highly recommended that you examine/listen to the underlying tracks detailed before purging.

{
  "ipod_data": {
    "playlists": {
      ...
    }
  },
  "ipod_analysis": {
    "duplicates": [
      {
        "match": "high",
        "tracks": []
      },
      {
        "match": "med",
        "tracks": []
      },
      {
        "match": "low",
        "tracks": [
          {
            "size": 8827352,
            "tracklen": 220000,
            "count": 1,
            "items": [
              {
                "id": 1361,
                "ipod_path": "/iPod_Control/Music/F08/NCQQ.mp3",
                "title": "foo",
                "artist": "Singer",
                "album": null,
                "genre": "Pop",
                "date_added": "2021-03-25T18:06:12"
              },
              {
                "id": 1366,
                "ipod_path": "/iPod_Control/Music/F41/ZNUF.mp3",
                "title": "bar",
                "artist": "Singer",
                "album": null,
                "genre": "Pop",
                "date_added": "2021-03-25T18:06:12"
              }
            ]
          }
        ]
      }
    ]
  }
}

To examine the main iPod playlist where all tracks are stored:

$ jq '.ipod_data.playlists.items[] | select(.type == "master")' ipod.json

Find all tracks for artist Foo but only get filename, title and id

$ jq '.ipod_data.playlists.items[] | select(.type == "master") | .tracks[] | select(.artist=="Foo") | {id, ipod_path, title, album}' ipod.json

gpod-rm

Removes track(s) from iPod. Requires the filename as known in the iTunesDB - see the output from gpod-ls.

$ gpod-rm -M /run/media/ray/IPOD \
    /iPod_Control/Music/F41/ZNUF.mp3
removing tracks from iPod Video (1st Gen.) A002, currently 88 tracks
[  1/1]  /iPod_Control/Music/F41/ZNUF.mp3 -> { id=1366 title='foo' artist='Foo&Bar' album='Test tracks' time_added=161672437 (2021-04-20T08:22:17)
sync'ing iPod ...
iPod total tracks=87  removed 1/1 items (58.32K)

The -a flag can be specified before any other files to force removal of duplicates files based on iPod filesystem checksums, leaving the earliest added instance of the track.

gpod-cp

Copies track(s) to iPod, accepting mp3, m4a/aac and h264 videos.. For audio files not supported by iPod an automatic conversion is performed. Using the -c switch controls audio checksum generation/analysis (ingnores metadata) of files on iPod to prevent duplicates being copied.

$ gpod-cp -M /run/media/ray/IPOD \
    nothere.mp3 foo.flac foo.mp3 foo.mp3
copying 4 tracks to iPod 9725 Shuffle (1st Gen.), currently 27 tracks
generating internal cksums...
processing 4 tracks over 8 threads
[  1/4]  nothere.mp3 -> { } No such file or directory
[  2/4]  foo.flac -> { title='Flac file' artist='Foo' album='Test tracks' ipod_path='/iPod_Control/Music/F00/libgpod325022.m4a' }
[  3/4]  foo.mp3 -> { title='mp3 file' artist='Foo' album='Test tracks' ipod_path='/iPod_Control/Music/F01/libgpod211429.mp3' }
[  4/4]  foo.mp3 -> { title='mp3 file' artist='Foo' album='Test tracks' ipod_path= *** DUPL 1503221223 *** }
sync'ing iPod ... 
iPod total tracks=29  2/4 items (3.44M)  music=2 video=0 other=0  in 0.572 secs (ttl xcode 0.355 secs)

The DUPL hashcode shows the audio stream of the file identified as duplicate - this integer value can be used to identify (via gpod-ls) on the track already on the iPod device; this hashcode especially useful as its generated on the audio stream which is independant of the metadata tags.

The quality of automatic audio conversions can be controlled by -q with values 0 (best) ..9 for VBR and 96,128,192,256,320 for CBR. The default conversion is to high quality vbr aac (equivalent to ffmpeg -c:a libfdk_aac -vbr 5) but conversions to mp3 and alac is also available via -e flag. Note that the aac conversion is dependant on ffmpeg supporting libfdk_aac (auto fallback conversion to mp3, equivalent to ffmpeg -c:a libmp3lame -vbr 1, if the fdk support is not available) - we avoid conversion using ffmpeg's internal aac encoder as it appears older iPod's can't play the files without glitches/artifacts. Metadata from the originating audio file can be copied to the transcoded file - this will be aid identifying files from the internal iPod storage at a later point.

iPod audio only support up to 48000 and we perform automatic sample rate conversions: Re-sampled audio files are not directly equivalent to ffmpeg, as verified by per-frame hash ffmpeg -i foo.mp3 -f framehash foo.sha256 or file stream hash ffmpeg -i foo.mp3 -c:a copy -bsf:a null -f hash -, although the non sample rate conversions are equivalent.

Note that the classic iPods (5th-7th generation) can only accept video files conforming to a h264 baseline in a m4v or mp4 container, up to 30fps, bitrate up to 2.5Mbbps and aac stereo audio up to 160kbps. Furthermore, iTunes will not copy video files to the iPod 5/5.5G that do not contain a special uuid atom encoded into the video file - however this does NOT prevent such files from being copied using gpod-cp and played on the iPod.

To test this, you can generate your own h264 files using ffmpeg -f rawvideo -video_size 640x320 -pixel_format yuv420p -framerate 23.976 -i /dev/random -f lavfi -i 'anoisesrc=color=brown' -c:a aac -b:a 96k -ar 44100 -t 10 -c:v libx264 -profile:v baseline -b:v 1.8M foo.mp4. This video will not contain the uuid atom.

To convert an existing video file for the iPod classics, you can use handbrake or ffmpeg directly:

# example iPod supported video transcode using:

# cuda/nvidia enabled ffmpeg
ffmpeg -hwaccel cuda  -hwaccel_output_format cuda  \
  -i foo.mp4 \
    -c:a aac -b:a 128k -ar 44100  \
    -f ipod \
    -c:v h264_nvenc -rc vbr_hq -minrate 1M -maxrate 2.5M \
    -profile:v baseline  \
    -vf scale_npp=640:-1 \
  bar.mp4

# quick sync video enabled ffmpeg
ffmpeg -hwaccel qsv \
  -c:v h264_qsv -i foo.mp4 \
    -c:a aac -b:a 128k -ar 44100  \
    -f ipod \
    -c:v h264_qsv -b:v 1.5M -minrate 500k -maxrate 2.5M \
    -vf scale_qsv=w=640:h=-1 \
  bar.mp4

The -f ipod flag will add the uuid attom. If the video file will be sync'd to your iPod 5G using gpod-cp then this flag is not necessary but is required if you with to use iTunes to perform the copy to the device.

The audio conversions are performed in their own threads and defaults to the number of cores on your system. This can be adjusted with the -T flag.

By default the copy will replace tracks (deleting existing version) with matchin title/artist/album - this assumes the user is intending to replace the tracks; this behaviour is governed by -r flag.

gpod-tag

Simple metadata tool to modify the iTunesDB. The underlying media files on the device are NOT updated. The internal id or ipod_path of the files are required and can be determined from gpod-ls. Use empty string ("") or -1 to unset the string and int tags respectively

$ gpod-tag -M /run/media/ray/IPOD -A "new album name" -y 2021  \
    9999 521 /iPod_Control/Music/F01/libgpod211429.mp3
updating iPod track meta { title='<nul>' artist='<nul>' album='new album name' genre='<nul>' track=-1 year=2021 } ...
[  1/3]  9999 { } - No such track
[  2/3]  521 { id=521 ipod_path='/iPod_Control/Music/F02/libgpod886634.m4a' { title='foo bar sings' artist='Foo&Bar' album='' genre='' track=2 year=0 time_modified=2021-04-01T11:43:29 } }
[  3/3]  /iPod_Control/Music/F01/libgpod211429.mp3 { id=534 ipod_path='/iPod_Control/Music/F01/libgpod211429.mp3' { title='A Song' artist='Foo&Bar' album='' genre='' track=2 year=0 time_modified=2021-04-01T13:03:09 } }
sync'ing iPod ... updated 2/3
updated iPod, total tracks=29

The metadata shown for each tracks is the existing data - the new metadata is show at the start of processing.

gpod-extract

Extracts all or select files from iPod and optionally sync'ing metadata (with -s flag) on the copied files to the iTunesDB values. No transcoding will be performed on the files, only generic metadata updates (as limited by ffmpeg).

$ gpod-extract -M /run/media/ray/IPOD -o /export/public/music/ -s /iPod_Control/Music/F02/libgpod886634.m4a ...
extracting 3 tracks from iPod Video (1st Gen.), currently 27 tracks
[  1/3]  id=521 /iPod_Control/Music/F02/libgpod886634.m4a -> '/export/pubic/music/Foo&Bar - foobar sings.m4a'
iPod total tracks=27  3/3 items (990.68K) in 0.107 secs

exiftool

exiftool can be further used to automatically organise files into directory structures if required.

# rename based on artist
$ exiftool '-filename<$Artist - $Title.%le' -r -ext mp3 -ext m4a .

# rename based on albums, creating the directory structure as necessary
$ exiftool '-filename<$Album/$Artist - $Title.%le' -r -ext mp3 -ext m4a .

gpod-verify

Verifies the iPod db aginst the files on the device. Three areas:

mode DB filesystem Comments
clean x not recoverable, delete from db
add x (-a) sync with filesystem, add to db
remove x (-d) sync with db, remove from filesystem
$ gpod-verify-M /run/media/ray/IPOD -a
validating tracks from iPod Video (2nd Gen.) A446, currently 4/4 db/filesystem tracks
CLEAN [  1]  /iPod_Control/Music/F13/libgpod031826.mp3 -> { id=52 title='some title' artist='foo' album='' time_added=1619260556 }
ADD   [  1]  /iPod_Control/Music/F00/foo.mp3 -> { title='Sine' artist='ffmpeg' album='' }
sync'ing iPod ...
iPod total tracks=4  orphaned 0 removed 1 added 1 items

gpod-hashsum

Generates the hashcode, based on the ffmpeg audio data stream's hash, used by gpod-cp for identifying duplicate files. Simple utility to validate input files.

About

Command line utilities to manage iPods (using libgpod), incl ls, cp with auto xcode, rm, edit track meta.


Languages

Language:C 99.5%Language:M4 0.2%Language:C++ 0.2%Language:Makefile 0.0%Language:Shell 0.0%