Creating an audio player that plays multiple tracks back-to-back

Hello, I am trying to create a way to easily play multiple audio back-to-back for my portfolio. I have nearly achieved it by grabbing info from a database, but after the second track, it stops doing its thing.

I have it update the title as well. If you know of a way to adding a skip feature that would be great!

Heres the code I have come up with so far:

import wixData from ‘wix-data’;

$w(“#audioPlayer1”).onEnded(async () => {
try {

    const result = await wixData.query("TrackInfo")
        .ascending("number")
        .find();

    if (result.items.length > 0) {
		let title = result.items[0].title;
		console.log("Title from database:", title);

        const nextAudio = result.items[0].audio;

        $w("#audioPlayer1").src = nextAudio;
		$w("#audioPlayer1").trackName = title;

        $w("#audioPlayer1").play();
    }
} catch (error) {
    console.error("Error fetching the next audio track:", error);
}

});

Hi, Phin_Vondenberger !!

It seems like the same track is being played every time, so if you want to move on to the next track, you’ll need to increment the index by +1. To do this, you should define a counter variable outside of the onEnded function. This variable should be incremented whenever a track ends. Additionally, when the last track has been played, you’ll need to reset the counter back to zero. :smiley:

1 Like

Thank you so much for the response! This seems like a great solution. While I understand the steps you explained, I am completely new to coding :sweat: could you please provide example code for what you mentioned? That would be extremely helpful :sweat_smile: I appreciate the help!

Hello, or good evening. I used the code you wrote as a reference to guide ChatGPT in creating this version. The logic behind it is something like this. However, to make it easier for you to understand, I based it on your original code, but I believe there’s still plenty of room for improvement. In fact, this code might not work as is. Modern browsers are designed not to allow audio playback without a user action, such as clicking a play button. So, while this code is written to automatically fetch song data from a database and start playing music once the page elements are loaded, there’s no guarantee it will function as intended.

If that’s the case, you’ll need to use a user action (e.g., clicking a play button) as the trigger for playing the first track. After the first track starts playing, the rest of the tracks should follow the flow of the code and play automatically. Additionally, I think it might not be necessary to access the database for song information every time. It could be more efficient to fetch the data once, store it, and have the player function handle looping playback. Alternatively, if the number of songs is small, you could even hard-code the song information into the code itself. (However, this approach has the drawback of making the song information visible to third parties through the browser’s developer tools.)

The reason I suggest minimizing database access is that it’s better to reduce the number of such operations whenever possible. If your site only has about ten visitors, it might not be an issue, but imagine if one million people visited your site. That would mean every time a track changes, one million browsers would access the database, resulting in a heavy load. Database access is one of the more resource-intensive operations in a system, so reducing the number of calls is usually beneficial.

This might be a bit advanced, but you could also make the code more reusable by structuring it into more general-purpose functions. As it stands, the onReady() function contains a lot of inline code. By extracting the logic into separate functions, including things like playTrack and currentTrackIndex, and defining them outside of onReady(), you can make the onReady() function much cleaner.

In such a case, the code inside onReady() would be reduced to three simple steps: fetching the song information, passing that information to a general-purpose function, and finally executing that function. If you’d like to organize the code to that extent, give it a try. This level of organization can improve readability, especially if you plan to add other processes to the onReady() function later on. However, it’s not strictly necessary. As long as the code inside onReady() is correct, it should work.

Based on the points I’ve mentioned here, you can likely achieve the desired code by consulting with ChatGPT or similar tools! Adding a skip button for tracks should also be possible! :wink:


import wixData from 'wix-data';

// Counter variable to manage the currently playing track
let currentTrackIndex = 0;

// Fetch track data when the page loads
$w.onReady(async () => {
    try {
        const result = await wixData.query("TrackInfo")
            .ascending("number") // Sort tracks in ascending order
            .find();

        if (result.items.length > 0) {
            // Save track data
            const trackList = result.items;

            // Play the first track
            playTrack(trackList, currentTrackIndex);

            // Move to the next track when the audio ends
            $w("#audioPlayer1").onEnded(() => {
                currentTrackIndex++; // Advance to the next track

                // If the last track has played, return to the first track
                if (currentTrackIndex >= trackList.length) {
                    currentTrackIndex = 0;
                }

                // Play the next track
                playTrack(trackList, currentTrackIndex);
            });
        } else {
            console.log("No tracks found in the database.");
        }
    } catch (error) {
        console.error("Error fetching track data:", error);
    }
});

// Function to play the track at the specified index
function playTrack(trackList, index) {
    const track = trackList[index];
    $w("#audioPlayer1").src = track.audio; // Set the audio URL of the track
    $w("#audioPlayer1").trackName = track.title; // Set the title of the track
    $w("#audioPlayer1").play(); // Start playback
    console.log(`Now playing: ${track.title}`);
}