<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Advanced Video Player</title> <style> body { font-family: Arial, sans-serif; margin: 0; padding: 10px; background: #f0f0f0; display: flex; flex-direction: column; align-items: center; } #player-container { width: 100%; max-width: 800px; background: #000; border-radius: 8px; overflow: hidden; box-shadow: 0 4px 8px rgba(0,0,0,0.2); } #video-player { width: 100%; height: auto; } #controls { display: flex; flex-wrap: wrap; align-items: center; padding: 10px; background: #333; color: #fff; gap: 5px; } #controls button, #controls select { padding: 5px 10px; background: #555; border: none; color: #fff; cursor: pointer; border-radius: 4px; font-size: 12px; } #controls button:hover, #controls select:hover { background: #777; } #seek-bar { flex-grow: 1; width: 100%; max-width: 300px; margin: 5px; } #volume-control { width: 80px; margin: 5px; } #playlist { width: 100%; max-width: 800px; margin-top: 10px; background: #fff; border-radius: 8px; box-shadow: 0 4px 8px rgba(0,0,0,0.2); max-height: 250px; overflow-y: auto; } .playlist-item { padding: 8px; border-bottom: 1px solid #ddd; cursor: pointer; font-size: 14px; transition: background 0.3s; } .playlist-item:hover { background: #f5f5f5; } .playlist-item.active { background: #ddd; font-weight: bold; } @media (max-width: 600px) { #controls { flex-direction: column; padding: 5px; } #controls button, #controls select { width: 100%; margin: 2px 0; } #seek-bar, #volume-control { width: 100%; max-width: none; } } </style> </head> <body> <div id="player-container"> <video id="video-player" controls></video> <div id="controls"> <button id="play-pause">Play</button> <button id="stop">Stop</button> <input type="range" id="seek-bar" value="0" min="0" max="100"> <input type="range" id="volume-control" value="1" min="0" max="1" step="0.1"> <button id="fullscreen">Fullscreen</button> <select id="playback-speed"> <option value="0.5">0.5x</option> <option value="1" selected>1x</option> <option value="1.5">1.5x</option> <option value="2">2x</option> </select> </div> </div> <div id="playlist"></div> <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script> <script> const videoPlayer = document.getElementById('video-player'); const playPauseBtn = document.getElementById('play-pause'); const stopBtn = document.getElementById('stop'); const seekBar = document.getElementById('seek-bar'); const volumeControl = document.getElementById('volume-control'); const fullscreenBtn = document.getElementById('fullscreen'); const playbackSpeed = document.getElementById('playback-speed'); const playlistDiv = document.getElementById('playlist'); let hls = null; let playlist = []; let currentVideoIndex = 0; fetch('https://raw.githubusercontent.com/Govexam/EXAMESINSIGHT/refs/heads/main/lectures.json') .then(response => { if (!response.ok) throw new Error('Failed to fetch JSON'); return response.json(); }) .then(data => { const videos = data.Bihar_Daroga_Prelims_Cum_Mains_Batch.Indian_Geography.Videos; playlist = Object.keys(videos).flatMap(section => videos[section].lectures.map(lecture => ({ title: lecture.video.title, url: lecture.video.url })) ); populatePlaylist(); loadVideo(currentVideoIndex); }) .catch(error => { console.error('Fetch Error:', error); playlistDiv.innerHTML = 'Error loading playlist. Check console.'; }); function populatePlaylist() { playlist.forEach((item, index) => { const div = document.createElement('div'); div.className = 'playlist-item'; div.textContent = item.title; div.addEventListener('click', () => { currentVideoIndex = index; loadVideo(currentVideoIndex); updatePlaylistUI(); }); playlistDiv.appendChild(div); }); updatePlaylistUI(); } function updatePlaylistUI() { const items = playlistDiv.children; for (let i = 0; i < items.length; i++) { items[i].classList.toggle('active', i === currentVideoIndex); } } function loadVideo(index) { const videoUrl = playlist[index].url; if (Hls.isSupported() && videoUrl.includes('hls')) { if (hls) hls.destroy(); hls = new Hls(); hls.loadSource(videoUrl); hls.attachMedia(videoPlayer); hls.on(Hls.Events.MANIFEST_PARSED, () => videoPlayer.play()); hls.on(Hls.Events.ERROR, (event, data) => { console.error('HLS Error:', data); playlistDiv.innerHTML += '<br>Error loading video: ' + playlist[index].title; }); } else { videoPlayer.src = videoUrl; videoPlayer.play().catch(err => console.error('Playback Error:', err)); } } playPauseBtn.addEventListener('click', () => { if (videoPlayer.paused) { videoPlayer.play(); playPauseBtn.textContent = 'Pause'; } else { videoPlayer.pause(); playPauseBtn.textContent = 'Play'; } }); stopBtn.addEventListener('click', () => { videoPlayer.pause(); videoPlayer.currentTime = 0; playPauseBtn.textContent = 'Play'; }); videoPlayer.addEventListener('timeupdate', () => { const value = (100 / videoPlayer.duration) * videoPlayer.currentTime; seekBar.value = value || 0; }); seekBar.addEventListener('input', () => { const time = videoPlayer.duration * (seekBar.value / 100); videoPlayer.currentTime = time; }); volumeControl.addEventListener('input', () => { videoPlayer.volume = volumeControl.value; }); fullscreenBtn.addEventListener('click', () => { if (videoPlayer.requestFullscreen) videoPlayer.requestFullscreen(); else if (videoPlayer.webkitRequestFullscreen) videoPlayer.webkitRequestFullscreen(); else if (videoPlayer.msRequestFullscreen) videoPlayer.msRequestFullscreen(); }); playbackSpeed.addEventListener('change', () => { videoPlayer.playbackRate = parseFloat(playbackSpeed.value); }); videoPlayer.addEventListener('ended', () => { currentVideoIndex = (currentVideoIndex + 1) % playlist.length; loadVideo(currentVideoIndex); updatePlaylistUI(); }); </script> </body> </html>