Last active
October 30, 2024 08:33
-
-
Save huynhbaoan/409e4acc25852cd3232d13c9d16475d7 to your computer and use it in GitHub Desktop.
Html player
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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