First I downloaded a list of all of my songs in an array in the format "Artist - Song Name" using the following script (pasted into the console on a Google Play page).
Note: If you want the data in alphabetical order by song name, you need to change the format from "Artist - Song Name" to "Song Name - Artist" in both this script and the playlist script I mention below.
(function () {
console.log("Just a moment locating music DB...");
const data = [];
indexedDB.databases().then(info => {
const name = data.dbName = info.find(db => db.name.indexOf("music_") === 0).name;
indexedDB.open(name).onsuccess = e => {
console.log("Extracting tracks from DB " + name);
const t = e.target.result.transaction("tracks", IDBTransaction.READ_ONLY);
t.oncomplete = () => {
Object.assign(document.createElement("a"), { download : name + ".tracks.txt", href: URL.createObjectURL(new Blob([JSON.stringify(data.sort())]), {type: "text/json" })})
.dispatchEvent(new MouseEvent("click", {view: window, bubbles: true, cancelable: true}));
}
t.objectStore("tracks").openCursor().onsuccess = e => {
if (e = e.target.result) {
Object.values(JSON.parse(e.value)).forEach(t => data.push(t[3] + " - " + t[1]));
e.continue();
}
}
}
}).catch(()=>console.log("Sorry, cannot complete data dump :("));
})()
Other potentially useful indexes: 4
for album, 11
for genre, and 13
for length.
Then I compared this list with my playlist text list using the following script and recorded all songs that are not found in the playlist file to a new file (I made a .html
page to make this easier - see this JSBin for a live example. Note that the text files should be in the JSON format that is the default of my exporting scripts).
<!DOCTYPE html>
<html>
<head>
<title>Google Play songs not in playlist</title>
</head>
<body>
<label>Song text file (generated from <a href="https://webapps.stackexchange.com/a/125423/140514">this answer</a>): <input type="file" id="songInput"></label>
<br>
<label>Playlist text file (generated from <a href="https://webapps.stackexchange.com/a/106604/140514">this answer</a>): <input type="file" id="playlistInput"></label>
<br>
<textarea style="width: 500px; height: 200px;"></textarea>
<script type="text/javascript">
var songInput = document.getElementById("songInput"),
playlistInput = document.getElementById("playlistInput"),
result = document.querySelector("textarea");
var songList,
playlistData;
function loadData(id, elem) {
if(elem.files
&& elem.files[0]) {
let myFile = elem.files[0];
let reader = new FileReader();
reader.addEventListener('load', function (e) {
if(id === "songInput")
songList = JSON.parse(e.target.result);
if(id === "playlistInput")
playlistData = e.target.result;
checkBothAdded();
});
reader.readAsBinaryString(myFile);
}
}
function checkBothAdded() {
if(songList
&& playlistData) {
getSongsNotInPlaylist();
}
}
var songsNotInPlaylist = [];
function getSongsNotInPlaylist() {
for(let song of songList) {
if(playlistData.indexOf(song) === -1) {
songsNotInPlaylist.push(song);
}
}
result.value = JSON.stringify(songsNotInPlaylist, null, '\t');
}
songInput.addEventListener("change", function() {
loadData("songInput", this);
});
playlistInput.addEventListener("change", function() {
loadData("playlistInput", this);
});
</script>
</body>
</html>