2

Related but distinct from my question on finding which playlists a particular song is in, is there any way to find songs in my Google Play library that are not in any playlists? Maybe a sort-by-number-of-playlists-it's-in feature?

I'd be fine with a userscript or third party solution, though obviously a built in way is preferable.

0

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>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.