Skip to content

Instantly share code, notes, and snippets.

@tillig
Created January 5, 2017 18:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tillig/2048bf75fd84c5717a47a0d7fc5e7fab to your computer and use it in GitHub Desktop.
Save tillig/2048bf75fd84c5717a47a0d7fc5e7fab to your computer and use it in GitHub Desktop.
Add cover art that iTunes downloaded so it's embedded into the track directly.
// Add-DownloadedCoverArtToFile.js
// By Travis Illig - http://www.paraesthesia.com
// THIS SCRIPT MODIFIES YOUR ITUNES TRACKS TO EMBED DOWNLOADED
// ARTWORK INTO TRACKS. USE AT YOUR OWN RISK. BACK UP YOUR FILES
// BEFORE RUNNING.
//
// Open iTunes, then run using cscript:
// cscript Add-DownloadedCoverArtToFile.js
// Set MAX_TRACKS_TO_PROCESS to the max number of tracks to process
// in a single script run. Since artwork processing can take a long
// time, if you have a large library you may not want the script running
// for hours to do the whole library at once.
var MAX_TRACKS_TO_PROCESS = 250;
// DON'T MODIFY BELOW THIS LINE
// unless you know what you're doing. :)
// Get the set of all tracks from the library.
var iTunesApp = WScript.CreateObject("iTunes.Application");
var allTracks = iTunesApp.LibraryPlaylist.Tracks;
if(allTracks == null)
{
WScript.Echo("Unable to get list of library tracks!");
WScript.Quit();
}
// Initialize some global values we'll use later.
var scriptWorkingDirectory = WScript.ScriptFullName.substr(0, WScript.ScriptFullName.length - WScript.ScriptName.length);
var fso = WScript.CreateObject("Scripting.FileSystemObject")
var numTracks = allTracks.Count;
var completePercent = 0;
var numProcessed = 0;
// Process the tracks.
for (var i = 1; i <= numTracks; i++)
{
var currentTrack = allTracks.Item(i);
// Only handle local tracks that aren't podcasts and that have downloaded art.
if(
currentTrack.URL != null ||
currentTrack.Podcast ||
currentTrack.Location == null ||
!HasDownloadedArtwork(currentTrack))
{
continue;
}
// Only handle tracks with ONE piece of artwork. If a track has multiple pieces
// of art, the order can be important and that's not something we want to deal with.
if(currentTrack.Artwork.Count > 1)
{
WScript.Echo("WARNING: '" + currentTrack.Name + "' has " + currentTrack.Artwork.Count + " pieces of art, one of which is downloaded. Process manually.");
continue;
}
try
{
WScript.Echo(" * " + currentTrack.Artist + " - " + currentTrack.Album + " - " + currentTrack.Name);
// Extract the art to a temp file, embed it in the track, and delete the temp file.
var tempFileName = scriptWorkingDirectory + CreateGuid() + ".bmp";
var artToSave = currentTrack.Artwork.Item(1);
artToSave.SaveArtworkToFile(tempFileName);
artToSave.Delete();
currentTrack.AddArtworkFromFile(tempFileName);
fso.DeleteFile(tempFileName);
}
catch(ex)
{
WScript.Echo("Error processing " + currentTrack.Artist + " - " + currentTrack.Name + ": " + ex);
}
// Provide a percent complete status message.
var currentComplete = Math.floor((i / numTracks) * 100);
if(currentComplete - completePercent >= 5)
{
completePercent = currentComplete;
WScript.Echo("Processed: " + completePercent + "% of library.");
}
// Bail early if we hit the max tracks to process.
numProcessed++;
if(numProcessed >= MAX_TRACKS_TO_PROCESS)
{
WScript.Echo("Ending processing early - reached max tracks to process (" + MAX_TRACKS_TO_PROCESS + ")");
break;
}
}
WScript.Echo("Done.");
// Checks a track to see if any piece of artwork associated
// is a downloaded art item.
function HasDownloadedArtwork(artTrack)
{
if(artTrack == null || artTrack.Artwork == null || artTrack.Artwork.Count == 0)
{
return false;
}
var artwork = artTrack.Artwork;
var numArtwork = artwork.Count;
for (var artCounter = 1; artCounter <= numArtwork; artCounter++)
{
var currentArtwork = artwork.Item(artCounter);
if(currentArtwork.IsDownloadedArtwork)
{
return true;
}
}
return false;
}
// Creates a new GUID that we can use as a temporary filename.
function CreateGuid()
{
var scriptTypeLib = new ActiveXObject("Scriptlet.TypeLib");
return scriptTypeLib.GUID.substr(1, 36);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment