#!/usr/bin/env ruby
# reviewed by Erik B on January 21 2012
# 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 selected tracks or if nothing selected entire library
# 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 'rubygems'
require 'appscript'
require 'json'
require 'open-uri'
class Track
attr_reader :iTunes_id
attr_reader :iTunes_track
def initialize(iTunes_track)
@iTunes_track = iTunes_track
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 #{iTunes_track.name.get}"
end
end
def valid?
@iTunes_id.nil?
end
def update_track(result)
@iTunes_track.name.set(result['trackName'])
@iTunes_track.album.set(result['collectionName'])
@iTunes_track.artist.set(result['artistName'])
@iTunes_track.track_count.set(result['trackCount'])
@iTunes_track.track_number.set(result['trackNumber'])
@iTunes_track.genre.set(result['primaryGenreName'])
@iTunes_track.disc_count.set(result['discCount'])
@iTunes_track.disc_number.set(result['discNumber'])
end
end
WORK_SIZE = 100
STDOUT.sync = true
tracks = []
app = Appscript.app.by_name("iTunes")
iTunes_tracks = app.selection.get
if iTunes_tracks.count == 0
iTunes_tracks = app.library_playlists[1].tracks.get
end
print "Reading #{iTunes_tracks.count} tracks "
iTunes_tracks.each do | iTunes_track |
begin
if iTunes_track.kind.get == 'Matched AAC audio file' or iTunes_track.kind.get == 'Fichier audio AAC acheté' or iTunes_track.kind.get =='Fichier audio AAC mis en correspondance' or iTunes_track.kind.get == 'Fichier audio AAC' or iTunes_track.kind.get == 'Abgeglichene AAC-Audiodatei'
track = Track.new(iTunes_track)
print "Track #{track}"
unless track.valid?
tracks << track
print '*' if ((tracks.count % WORK_SIZE) == 0)
end
end
rescue StandardError => e
puts e
end
end
puts ''
# all 2 char countries codes lots currently not valid %w(AF AX AL DZ AS AD AO AI AQ AG AR AM AW AU AT AZ BS BH BD BB BY BE BZ BJ BM BT BO BQ BA BW BV BR IO BN BG BF BI KH CM CA CV KY CF TD CL CN CX CC CO KM CG CD CK CR CI HR CU CW CY CZ DK DJ DM DO EC EG SV GQ ER EE ET FK FO FJ FI FR GF PF TF GA GM GE DE GH GI GR GL GD GP GU GT GG GN GW GY HT HM VA HN HK HU IS IN ID IR IQ IE IM IL IT JM JP JE JO KZ KE KI KP KR KW KG LA LV LB LS LR LY LI LT LU MO MK MG MW MY MV ML MT MH MQ MR MU YT MX FM MD MC MN ME MS MA MZ MM NA NR NP NL NC NZ NI NE NG NU NF MP NO OM PK PW PS PA PG PY PE PH PN PL PT PR QA RE RO RU RW BL SH KN LC MF PM VC WS SM ST SA SN RS SC SL SG SX SK SI SB SO ZA GS SS ES LK SD SR SJ SZ SE CH SY TW TJ TZ TH TL TG TK TO TT TN TR TM TC TV UG UA AE GB US UM UY UZ VU VE VN VG VI WF EH YE ZM ZW)
countries = %w(US GB AU FR DE CA IT JP DZ AO AI AG AR AM AT AZ BS BH BD BB BY BE BZ BM BO BW BR BN BG CM KY CL CN CO CR CI HR CY CZ DK DM DO EC EG SV EE ET FI GH GR GD GT GY HN HK HU IS IN ID IE IL JM JO KZ KE KR KW LV LB LY LI LT LU MO MK MG MY MV ML MT MU MX MD MS MM NP NL NZ NI NE NG NO OM PK PA PY PE PH PL PT QA RO RU KN LC VC SA SN RS SG SK SI ZA ES LK SR SE CH TW TZ TH TT TN TR TC UG UA AE UY UZ VE VN VG YE)
puts "Found #{tracks.count} matched tracks"
countries.each do | country |
print "Querying #{country} store for #{tracks.count} tracks "
counter = 0
tracks.dup.each.each_slice(WORK_SIZE) do | subtracks |
ids = subtracks.map { | track | track.iTunes_id }
iTunesHash = JSON.parse(open("http://itunes.apple.com/lookup?id=#{ids.join(',')}&country=#{country}").read)
print '*'
iTunesHash['results'].each do | result |
result_id = result['trackId']
subtracks.each do | track |
if result_id == track.iTunes_id
track.update_track(result)
tracks.delete(track)
counter += 1
break
end
end
end
end
puts " #{counter} updated"
break if tracks.empty?
end
puts "Couldn't find meatadata for #{tracks.count} tracks" if tracks.count != 0
#!/usr/bin/env ruby
# reviewed by Erik B on January 21 2012
# 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 selected tracks or if nothing selected entire library
# 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 'rubygems'
require 'appscript'
require 'json'
require 'open-uri'
class Track
attr_reader :iTunes_id
attr_reader :iTunes_track
def initialize(iTunes_track)
@iTunes_track = iTunes_track
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 #{iTunes_track.name.get}"
end
end
def valid?
@iTunes_id.nil?
end
def update_track(result)
@iTunes_track.name.set(result['trackName'])
@iTunes_track.album.set(result['collectionName'])
@iTunes_track.artist.set(result['artistName'])
@iTunes_track.track_count.set(result['trackCount'])
@iTunes_track.track_number.set(result['trackNumber'])
if result['primaryGenreName'] != nil
@iTunes_track.genre.set(result['primaryGenreName'])
end
@iTunes_track.disc_count.set(result['discCount'])
@iTunes_track.disc_number.set(result['discNumber'])
@iTunes_track.album_artist.set(result['artistName'])
if result['releaseDate'] != nil
releasedate = result['releaseDate']
releaseyear = releasedate[0..3]
@iTunes_track.year.set(releaseyear)
end
end
end
WORK_SIZE = 100
STDOUT.sync = true
tracks = []
app = Appscript.app.by_name("iTunes")
iTunes_tracks = app.selection.get
if iTunes_tracks.count == 0
iTunes_tracks = app.library_playlists[1].tracks.get
end
print "Reading #{iTunes_tracks.count} tracks "
iTunes_tracks.each do | iTunes_track |
begin
if iTunes_track.kind.get == 'Matched AAC audio file' or iTunes_track.kind.get == 'Gematcht AAC-audiobestand' or iTunes_track.kind.get == 'Fichier audio AAC acheté' or iTunes_track.kind.get == 'Abgeglichene AAC-Audiodatei'
track = Track.new(iTunes_track)
print "Track #{track}"
unless track.valid?
tracks << track
print '*' if ((tracks.count % WORK_SIZE) == 0)
end
end
rescue StandardError => e
puts e
end
end
puts ''
# all 2 char countries codes lots currently not valid %w(AF AX AL DZ AS AD AO AI AQ AG AR AM AW AU AT AZ BS BH BD BB BY BE BZ BJ BM BT BO BQ BA BW BV BR IO BN BG BF BI KH CM CA CV KY CF TD CL CN CX CC CO KM CG CD CK CR CI HR CU CW CY CZ DK DJ DM DO EC EG SV GQ ER EE ET FK FO FJ FI FR GF PF TF GA GM GE DE GH GI GR GL GD GP GU GT GG GN GW GY HT HM VA HN HK HU IS IN ID IR IQ IE IM IL IT JM JP JE JO KZ KE KI KP KR KW KG LA LV LB LS LR LY LI LT LU MO MK MG MW MY MV ML MT MH MQ MR MU YT MX FM MD MC MN ME MS MA MZ MM NA NR NP NL NC NZ NI NE NG NU NF MP NO OM PK PW PS PA PG PY PE PH PN PL PT PR QA RE RO RU RW BL SH KN LC MF PM VC WS SM ST SA SN RS SC SL SG SX SK SI SB SO ZA GS SS ES LK SD SR SJ SZ SE CH SY TW TJ TZ TH TL TG TK TO TT TN TR TM TC TV UG UA AE GB US UM UY UZ VU VE VN VG VI WF EH YE ZM ZW)
countries = %w(US GB AU FR DE CA IT JP DZ AO AI AG AR AM AT AZ BS BH BD BB BY BE BZ BM BO BW BR BN BG CM KY CL CN CO CR CI HR CY CZ DK DM DO EC EG SV EE ET FI GH GR GD GT GY HN HK HU IS IN ID IE IL JM JO KZ KE KR KW LV LB LY LI LT LU MO MK MG MY MV ML MT MU MX MD MS MM NP NL NZ NI NE NG NO OM PK PA PY PE PH PL PT QA RO RU KN LC VC SA SN RS SG SK SI ZA ES LK SR SE CH TW TZ TH TT TN TR TC UG UA AE UY UZ VE VN VG YE)
puts "Found #{tracks.count} matched tracks"
countries.each do | country |
print "Querying #{country} store for #{tracks.count} tracks "
counter = 0
tracks.dup.each.each_slice(WORK_SIZE) do | subtracks |
ids = subtracks.map { | track | track.iTunes_id }
iTunesHash = JSON.parse(open("http://itunes.apple.com/lookup?id=#{ids.join(',')}&country=#{country}").read)
print '*'
iTunesHash['results'].each do | result |
result_id = result['trackId']
subtracks.each do | track |
if result_id == track.iTunes_id
track.update_track(result)
tracks.delete(track)
counter += 1
break
end
end
end
end
puts " #{counter} updated"
break if tracks.empty?
end
puts "Couldn't find meatadata for #{tracks.count} tracks" if tracks.count != 0
Hi all,
@Schirkan, you had a great idea to adapt the Ruby script to Windows. Unfortunately, I can't make it works. I always have the result: "0 tracks found". I'm in Peru, I have my iTunes Match account in Peru, in French language; I tried tu switch iTunes in few languages and I also tried with another iTunes accounts in USA and France (but both without iTunes Match). And the result is always the same Any idea?
Please check my screencopy. It's just an example; the result is the same with any track.
Thank you.
if iTunes_track.kind.get == 'Matched AAC audio file' or iTunes_track.kind.get == 'Fichier audio AAC acheté' or iTunes_track.kind.get =='Fichier audio AAC mis en correspondance' or iTunes_track.kind.get == 'Fichier audio AAC' or iTunes_track.kind.get == 'Abgeglichene AAC-Audiodatei'
Here the condition updated in ruby
Code:if iTunes_track.kind.get == 'Matched AAC audio file' or iTunes_track.kind.get == 'Fichier audio AAC acheté' or iTunes_track.kind.get =='Fichier audio AAC mis en correspondance' or iTunes_track.kind.get == 'Fichier audio AAC' or iTunes_track.kind.get == 'Abgeglichene AAC-Audiodatei'
"5000.006" = "Fichier audio AAC";
"5000.008" = "Fichier audio AAC protégé";
"5000.010" = "Fichier audio AAC acheté";
"5000.011" = "Fichier audio AAC mis en correspondance";
"5000.006" = "AAC audio file";
"5000.008" = "Protected AAC audio file";
"5000.010" = "Purchased AAC audio file";
"5000.011" = "Matched AAC audio file";
"5000.006" = "AAC-Audiodatei";
"5000.008" = "Geschützte AAC-Audiodatei";
"5000.010" = "Gekaufte AAC-Audiodatei";
"5000.011" = "Abgeglichene AAC-Audiodatei";
"5000.006" = "Archivo de audio AAC";
"5000.008" = "Archivo de audio AAC protegido";
"5000.010" = "Archivo de audio AAC comprado";
"5000.011" = "Archivo de audio AAC coincidente";
"5000.006" = "Arq. áudio AAC";
"5000.008" = "Arq. áudio AAC prot.";
"5000.010" = "Arq. áudio AAC compr.";
"5000.011" = "Arq. áudio AAC disponibilizado";
"5000.006" = "Áudio AAC";
"5000.008" = "Áudio AAC protegido";
"5000.010" = "Áudio AAC comprado";
"5000.011" = "Ficheiro de áudio AAC correspondente";
"5000.006" = "AAC-ljudfil";
"5000.008" = "Skyddad AAC-ljudfil";
"5000.010" = "Köpt AAC-ljudfil";
"5000.011" = "Matchad AAC-ljudfil";
"5000.006" = "Doc. audio AAC";
"5000.008" = "Doc. audio AAC protetto";
"5000.010" = "Doc. audio AAC acquistato";
"5000.011" = "Doc. audio AAC corrispondente";
"5000.006" = "AAC-audiobestand";
"5000.008" = "Beveiligd AAC-audiobestand";
"5000.010" = "Aangeschaft AAC-audiobestand";
"5000.011" = "Gematcht AAC-audiobestand";
"5000.006" = "AAC オーディオファイル";
"5000.008" = "保護された AAC オーディオファイル";
"5000.010" = "購入した AAC オーディオファイル";
"5000.011" = "一致した AAC オーディオファイル";
cd /Applications/iTunes.app/Contents/Resources
ls -d *.lproj
Dutch.lproj Japanese.lproj fi.lproj pt.lproj zh_CN.lproj
English.lproj Spanish.lproj hu.lproj pt_PT.lproj zh_TW.lproj
French.lproj cs.lproj ko.lproj ru.lproj
German.lproj da.lproj no.lproj sv.lproj
Italian.lproj en_GB.lproj pl.lproj tr.lproj
cd sv.lproj
iconv -f UTF-16 -t UTF-8 Localizable.strings | grep 'AAC'
New version 1.2 is available: Download
iTunes-Language support for: german, english, frensch, dutch, spanish, portuguese, swedish, italian and japanese
thx to ebengtso
Only tested with german iTunes...
I can't get the script to work on my Mac.
Is it possible for someone to make a nice app for a mac?
if iTunes_track.kind.get == 'Matched AAC audio file' or iTunes_track.kind.get == 'Gematcht AAC-audiobestand' or iTunes_track.kind.get == 'Fichier audio AAC acheté' or iTunes_track.kind.get == 'Abgeglichene AAC-Audiodatei'
if iTunes_track.kind.get == 'Matched AAC audio file' or iTunes_track.kind.get == 'Gematcht AAC-audiobestand' or iTunes_track.kind.get == 'Fichier audio AAC acheté' or iTunes_track.kind.get == 'Abgeglichene AAC-Audiodatei' or iTunes_track.kind.get == 'Passende AAC-Audiodatei'
Any way to do this on windows yet? Would love to have all my tracks fully tagged.
@ imthenachoman
sorry not going to be able to answer your question but maybe you can help me with one. can i ask how were you able to view what track id is attached to the file?
i'm quite interested in seeing what the track id is for certain tracks to identify which album it's come from.
thanks..
# need this package
from struct import unpack
# open the file in byte mode and read the 1024 bytes
data = open( "/path/to/file", "rb" ).read( 1024 )
# find the index of "song" which is where the track ID starts
index = data.index( "song" )
# if we found an index unpack the next 4 bytes starting from index and get the first item
if( index )
trackID = unpack( "!I", data[index+4:index+4+4] )[0]