Skip to content

Instantly share code, notes, and snippets.

@huynhbaoan
Last active October 30, 2024 08:33
Show Gist options
  • Save huynhbaoan/409e4acc25852cd3232d13c9d16475d7 to your computer and use it in GitHub Desktop.
Save huynhbaoan/409e4acc25852cd3232d13c9d16475d7 to your computer and use it in GitHub Desktop.
Html player
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Playlist with Multiple Videos and Timed Switching</title>
</head>
<body>
<h1>YouTube Playlist</h1>
<h2 id="song-title"></h2> <!-- Song title will appear here -->
<div id="player"></div>
<button id="prevButton">Previous</button>
<button id="nextButton">Next</button>
<button id="shuffleButton">Shuffle</button>
<p id="error-message" style="color: red;"></p> <!-- Display error messages -->
<script>
// Load the YouTube IFrame Player API code
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var player;
var timer; // Global variable to hold the timer
var playlist = [
//{videoId: "pS-AWIfuBNE", startSeconds: 0, endSeconds: 0, title: "Gimme! Gimme! Gimme! (ABBA) | EPIC ORCHESTRAL COVER"},
//{videoId: "5RtFA3IojOE", startSeconds: 0, endSeconds: 0, title: "The Final Countdown (Europe) | EPIC ORCHESTRAL COVER"},
//{videoId: "htekfsbqqwc", startSeconds: 0, endSeconds: 0, title: "SYMPHONIKA ON THE ROCK - The Final Countdown | Europe Cover - Rock Orchestra"},
{videoId: "pICAha0nsb0", startSeconds: 0, endSeconds: 0, title: "Two Steps From Hell - Star Sky"},
{videoId: "n-Dh3ftkRAs", startSeconds: 0, endSeconds: 0, title: "Two Steps From Hell - Flight of the Silverbird"},
{videoId: "RKmw9oS__MM", startSeconds: 0, endSeconds: 0, title: "Two Steps From Hell - Cannon in D Minor"},
{videoId: "hKRUPYrAQoE", startSeconds: 0, endSeconds: 0, title: "Two Steps From Hell - Victory"},
{videoId: "jIxas0a-KgM", startSeconds: 0, endSeconds: 0, title: "Two Steps From Hell - Strength of a Thousand Men (Archangel)"},
{videoId: "R7WFzpWQ6-c", startSeconds: 0, endSeconds: 0, title: "Two Steps From Hell - Archangel (Archangel)"},
{videoId: "vbttZVTSJRU", startSeconds: 5, endSeconds: 0, title: "Two Steps From Hell - Blackheart (SkyWorld)"},
{videoId: "qiB98Wbsdlo", startSeconds: 5, endSeconds: 0, title: "Two Steps From Hell - El Dorado (SkyWorld)"},
{videoId: "ibufSTLNQrU", startSeconds: 0, endSeconds: 0, title: "Thomas Bergersen - Mountain Call"},
{videoId: "GDWnpSR9Tas", startSeconds: 0, endSeconds: 0, title: "Rasputin (Boney M.) | EPIC ORCHESTRAL COVER"},
{videoId: "UUcnw1iNN-8", startSeconds: 0, endSeconds: 0, title: "Katyusha (Катюша) | Orchestral Performance"},
{videoId: "rlDoFUzFqho", startSeconds: 0, endSeconds: 0, title: "Moskau (Dschinghis Khan) | EPIC ORCHESTRAL COVER"},
{videoId: "BFpjbckH-hY", startSeconds: 0, endSeconds: 0, title: "Canon in D - Hungarian Dance Style (Pachelbel meets Brahms) | Epic Orchestral"},
{videoId: "xA3px-brPWo", startSeconds:0, endSeconds: 600, title: "交响组曲·刀剑神域 | ソードアート・オンライン | Sword Art Online"},
//{videoId: "", startSeconds:0, endSeconds: 0, title: ""},
];
var currentIndex = 0;
var shuffledPlaylist = [];
var isShuffled = false;
// Function that loads the player
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '315',
width: '560',
videoId: playlist[currentIndex].videoId,
playerVars: {
'autoplay': 1,
'start': playlist[currentIndex].startSeconds
},
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange,
'onError': onPlayerError // Handle player errors
}
});
}
// Function to handle when the player is ready
function onPlayerReady(event) {
loadVideo();
}
// Function to handle video state changes
function onPlayerStateChange(event) {
if (event.data === YT.PlayerState.ENDED) {
playNext();
}
}
// Function to handle video loading errors
function onPlayerError(event) {
var errorMessage = document.getElementById('error-message');
var currentVideoTitle = getCurrentVideo().title; // Get the title of the video that caused the error
switch (event.data) {
case 2:
errorMessage.textContent = `Error with video: "${currentVideoTitle}". Invalid video ID.`;
break;
case 5:
errorMessage.textContent = `Error with video: "${currentVideoTitle}". The video is not available in HTML5.`;
break;
case 100:
errorMessage.textContent = `Error with video: "${currentVideoTitle}". Video not found.`;
break;
case 101:
case 150:
errorMessage.textContent = `Error with video: "${currentVideoTitle}". Embedding of this video has been disabled. Skipping to next video.`;
break;
default:
errorMessage.textContent = `Error with video: "${currentVideoTitle}". An unknown error occurred.`;
}
// Skip to the next video if there's an error
playNext();
}
// Function to load and play a video
function loadVideo() {
var currentVideo = getCurrentVideo();
if (currentVideo.videoId) {
player.loadVideoById({
videoId: currentVideo.videoId,
startSeconds: currentVideo.startSeconds
});
// Clear any existing timer before starting a new one
clearExistingTimer();
// Set the timer for the current song
if (currentVideo.endSeconds > 0) {
var duration = (currentVideo.endSeconds - currentVideo.startSeconds + 5) * 1000;
timer = setTimeout(function() {
playNext(); // Automatically switch to the next track when the timer expires
}, duration);
}
}
updateSongTitle();
}
// Function to play the next track
function playNext() {
clearExistingTimer(); // Clear the current timer
currentIndex++;
if (currentIndex >= getPlaylistLength()) {
currentIndex = 0; // Loop back to the first song if it's the last one
}
loadVideo();
}
// Function to play the previous track
function playPrevious() {
clearExistingTimer(); // Clear the current timer
currentIndex--;
if (currentIndex < 0) {
currentIndex = getPlaylistLength() - 1; // Loop back to the last song if it's the first one
}
loadVideo();
}
// Function to clear any existing timer
function clearExistingTimer() {
if (timer) {
clearTimeout(timer); // Clear the timer if it exists
timer = null; // Reset the timer variable
}
}
// Function to update the song title
function updateSongTitle() {
var songTitleElement = document.getElementById('song-title');
songTitleElement.textContent = getCurrentVideo().title;
}
// Function to shuffle the playlist
function shufflePlaylist() {
isShuffled = !isShuffled;
if (isShuffled && shuffledPlaylist.length === 0) { // Only shuffle once
shuffledPlaylist = [...playlist];
for (let i = shuffledPlaylist.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffledPlaylist[i], shuffledPlaylist[j]] = [shuffledPlaylist[j], shuffledPlaylist[i]];
}
}
currentIndex = 0;
loadVideo();
}
// Helper function to get the current video
function getCurrentVideo() {
return isShuffled ? shuffledPlaylist[currentIndex] : playlist[currentIndex];
}
// Helper function to get the length of the current playlist
function getPlaylistLength() {
return isShuffled ? shuffledPlaylist.length : playlist.length;
}
// Add event listeners to the buttons
document.getElementById('nextButton').addEventListener('click', playNext);
document.getElementById('prevButton').addEventListener('click', playPrevious);
document.getElementById('shuffleButton').addEventListener('click', shufflePlaylist);
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Playlist with Multiple Videos and Timed Switching</title>
</head>
<body>
<h1>YouTube Playlist</h1>
<h2 id="song-title"></h2> <!-- Song title will appear here -->
<div id="player"></div>
<button id="prevButton">Previous</button>
<button id="nextButton">Next</button>
<button id="shuffleButton">Shuffle</button>
<p id="error-message" style="color: red;"></p> <!-- Display error messages -->
<script>
// Load the YouTube IFrame Player API code
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var player;
var timer; // Global variable to hold the timer
var playlist = [
{videoId: "pS-AWIfuBNE", startSeconds: 0, endSeconds: 60, title: "Gimme! Gimme! Gimme! (ABBA) | EPIC ORCHESTRAL COVER"},
{videoId: "5RtFA3IojOE", startSeconds: 0, endSeconds: 90, title: "The Final Countdown (Europe) | EPIC ORCHESTRAL COVER"},
{videoId: "htekfsbqqwc", startSeconds: 0, endSeconds: 70, title: "SYMPHONIKA ON THE ROCK - The Final Countdown | Europe Cover - Rock Orchestra"},
{videoId: "pICAha0nsb0", startSeconds: 0, endSeconds: 60, title: "Two Steps From Hell - Star Sky"},
{videoId: "n-Dh3ftkRAs", startSeconds: 0, endSeconds: 80, title: "Two Steps From Hell - Flight of the Silverbird"},
{videoId: "RKmw9oS__MM", startSeconds: 0, endSeconds: 75, title: "Two Steps From Hell - Cannon in D Minor"},
{videoId: "hKRUPYrAQoE", startSeconds: 0, endSeconds: 85, title: "Two Steps From Hell - Victory"},
{videoId: "jIxas0a-KgM", startSeconds: 0, endSeconds: 90, title: "Two Steps From Hell - Strength of a Thousand Men (Archangel)"},
{videoId: "R7WFzpWQ6-c", startSeconds: 0, endSeconds: 90, title: "Two Steps From Hell - Archangel (Archangel)"},
{videoId: "vbttZVTSJRU", startSeconds: 5, endSeconds: 70, title: "Two Steps From Hell - Blackheart (SkyWorld)"},
{videoId: "qiB98Wbsdlo", startSeconds: 5, endSeconds: 70, title: "Two Steps From Hell - El Dorado (SkyWorld)"},
{videoId: "ibufSTLNQrU", startSeconds: 0, endSeconds: 80, title: "Thomas Bergersen - Mountain Call"},
{videoId: "GDWnpSR9Tas", startSeconds: 0, endSeconds: 90, title: "Rasputin (Boney M.) | EPIC ORCHESTRAL COVER"},
{videoId: "UUcnw1iNN-8", startSeconds: 0, endSeconds: 60, title: "Katyusha (Катюша) | Orchestral Performance"},
{videoId: "rlDoFUzFqho", startSeconds: 0, endSeconds: 60, title: "Moskau (Dschinghis Khan) | EPIC ORCHESTRAL COVER"},
{videoId: "BFpjbckH-hY", startSeconds: 0, endSeconds: 60, title: "Canon in D - Hungarian Dance Style (Pachelbel meets Brahms) | Epic Orchestral"},
{videoId: "", startSeconds: 0, endSeconds: 0, title: ""},
];
var currentIndex = 0;
var shuffledPlaylist = [];
var isShuffled = false;
// Function that loads the player
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '315',
width: '560',
videoId: playlist[currentIndex].videoId,
playerVars: {
'autoplay': 1,
'start': playlist[currentIndex].startSeconds
},
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange,
'onError': onPlayerError // Handle player errors
}
});
}
// Function to handle when the player is ready
function onPlayerReady(event) {
loadVideo();
}
// Function to handle video state changes
function onPlayerStateChange(event) {
if (event.data === YT.PlayerState.ENDED) {
playNext();
}
}
// Function to handle video loading errors
function onPlayerError(event) {
var errorMessage = document.getElementById('error-message');
var currentVideoTitle = getCurrentVideo().title; // Get the title of the video that caused the error
switch (event.data) {
case 2:
errorMessage.textContent = `Error with video: "${currentVideoTitle}". Invalid video ID.`;
break;
case 5:
errorMessage.textContent = `Error with video: "${currentVideoTitle}". The video is not available in HTML5.`;
break;
case 100:
errorMessage.textContent = `Error with video: "${currentVideoTitle}". Video not found.`;
break;
case 101:
case 150:
errorMessage.textContent = `Error with video: "${currentVideoTitle}". Embedding of this video has been disabled. Skipping to next video.`;
break;
default:
errorMessage.textContent = `Error with video: "${currentVideoTitle}". An unknown error occurred.`;
}
// Skip to the next video if there's an error
playNext();
}
// Function to load and play a video
function loadVideo() {
var currentVideo = getCurrentVideo();
if (currentVideo.videoId) {
player.loadVideoById({
videoId: currentVideo.videoId,
startSeconds: currentVideo.startSeconds
});
// Clear any existing timer before starting a new one
clearExistingTimer();
// Set the timer for the current song
if (currentVideo.endSeconds > 0) {
var duration = (currentVideo.endSeconds - currentVideo.startSeconds) * 1000;
timer = setTimeout(function() {
playNext(); // Automatically switch to the next track when the timer expires
}, duration);
}
}
updateSongTitle();
}
// Function to play the next track
function playNext() {
clearExistingTimer(); // Clear the current timer
currentIndex++;
if (currentIndex >= getPlaylistLength()) {
currentIndex = 0; // Loop back to the first song if it's the last one
}
loadVideo();
}
// Function to play the previous track
function playPrevious() {
clearExistingTimer(); // Clear the current timer
currentIndex--;
if (currentIndex < 0) {
currentIndex = getPlaylistLength() - 1; // Loop back to the last song if it's the first one
}
loadVideo();
}
// Function to clear any existing timer
function clearExistingTimer() {
if (timer) {
clearTimeout(timer); // Clear the timer if it exists
timer = null; // Reset the timer variable
}
}
// Function to update the song title
function updateSongTitle() {
var songTitleElement = document.getElementById('song-title');
songTitleElement.textContent = getCurrentVideo().title;
}
// Function to shuffle the playlist
function shufflePlaylist() {
isShuffled = !isShuffled;
if (isShuffled && shuffledPlaylist.length === 0) { // Only shuffle once
shuffledPlaylist = [...playlist];
for (let i = shuffledPlaylist.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffledPlaylist[i], shuffledPlaylist[j]] = [shuffledPlaylist[j], shuffledPlaylist[i]];
}
}
currentIndex = 0;
loadVideo();
}
// Helper function to get the current video
function getCurrentVideo() {
return isShuffled ? shuffledPlaylist[currentIndex] : playlist[currentIndex];
}
// Helper function to get the length of the current playlist
function getPlaylistLength() {
return isShuffled ? shuffledPlaylist.length : playlist.length;
}
// Add event listeners to the buttons
document.getElementById('nextButton').addEventListener('click', playNext);
document.getElementById('prevButton').addEventListener('click', playPrevious);
document.getElementById('shuffleButton').addEventListener('click', shufflePlaylist);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment