Skip to content

Instantly share code, notes, and snippets.

@hube
Last active July 13, 2017 07:38
Show Gist options
  • Save hube/9055dc2b88f7107751aa5c99a40117e6 to your computer and use it in GitHub Desktop.
Save hube/9055dc2b88f7107751aa5c99a40117e6 to your computer and use it in GitHub Desktop.
Apple Music Metadata Matching Script (originally taken from https://cl.ly/C3kK)
#!/usr/bin/env ruby
# by @tapbot_paul
# Don't blame me if this nukes your metadata, formats your drive, kills your kids
# This script goes through any iCloud Matched songs in your iTunes library and tries to update the
# metadata from the iTunes Store
# Will run against entire library
# Known to work with Ruby 1.9.3-p551, macOS 10.12.5, iTunes 12.6.1.25
# install the required gems with the following commands
# sudo gem install json
# sudo gem install rb-appscript
# then run the script with "ruby meta.rb"
require 'appscript'
require 'json'
require 'open-uri'
class Track
attr_reader :itunes_track
def initialize(itunes_track)
@itunes_track = itunes_track
end
def itunes_id
return @itunes_id if !@itunes_id.nil?
path = @itunes_track.location.get.path
file_string = File.open(path, 'r').read(1024) # data always seems to be around 600-700 bytes in
index = file_string.index('song')
if index
@itunes_id = file_string[index+4, 4].unpack('N')[0]
else
puts "Couldn't find @itunes_track id #{track.name.get}"
end
end
def has_itunes_id?
!itunes_id.nil?
end
def name
@itunes_track.name.get
end
def artist
@itunes_track.artist.get
end
def update(result)
@itunes_track.artist.set(result['artistName'])
@itunes_track.album.set(result['collectionName'])
@itunes_track.name.set(result['trackName'])
@itunes_track.year.set(Date.parse(result['releaseDate']).year)
@itunes_track.disc_count.set(result['discCount'])
@itunes_track.disc_number.set(result['discNumber'])
@itunes_track.track_count.set(result['trackCount'])
@itunes_track.track_number.set(result['trackNumber'])
@itunes_track.genre.set(result['primaryGenreName'])
# @itunes_track.album_artist.set(result['artistName'])
@itunes_track.comment.set('')
@itunes_track.composer.set('')
@itunes_track.grouping.set('')
@itunes_track.bpm.set('')
@itunes_track.lyrics.set('')
end
end
all_tracks = Appscript.app.by_name("iTunes").library_playlists[1].tracks.get
matched_tracks = Hash.new { |hash, key| hash[key] = [] }
all_tracks.each do |track|
if track.kind.get == 'Matched AAC audio file'
matched_track = Track.new(track)
if matched_track.has_itunes_id?
matched_tracks[matched_track.itunes_id] << matched_track
else
raise "Track #{matched_track.name.inspect} by #{matched_track.artist.inspect} has no iTunes ID"
end
end
end
puts "Found #{matched_tracks.size} unique tracks out of #{all_tracks.size} total tracks"
WORK_SIZE = 100
counter = 0
matched_tracks.keys.each_slice(WORK_SIZE).with_index do |track_ids, index|
puts WORK_SIZE * (index + 1)
updated_tracks = []
# Country defaults to US, lang defaults to en
track_data = JSON.parse(open("http://itunes.apple.com/lookup?id=#{track_ids.join(',')}").read)
# For retrieving Chinese track data
# track_data = JSON.parse(open("http://itunes.apple.com/lookup?id=#{track_ids.join(',')}&country=HK&lang=zh_HK").read)
track_data['results'].each do |result|
result_id = result['trackId']
matched_tracks[result_id].each do |track|
track.update(result)
end
counter += 1
updated_tracks << result_id
end
missing_tracks = track_ids - updated_tracks
if missing_tracks.size > 0
puts "Missed tracks:"
puts missing_tracks.inspect
end
end
puts "Matched #{counter} tracks out of #{matched_tracks.size}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment