Player Audio Yooutube - List taken form text
file list (list1.txt, list2.txt, dll.)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>YouTube Video List</title>
<!-- Bootstrap CSS -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
<!-- Font Awesome CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
<style>
.thumbnail {
width: 50px;
height: auto;
margin-right: 10px;
}
.list-group-item {
display: flex;
align-items: center;
}
.play-icon {
margin-left: auto;
font-size: 24px;
cursor: pointer;
}
.youtube-audio-player {
display: none;
position: fixed;
bottom: 0;
left: 5%;
width: 90%;
background: #f8f9fa;
box-shadow: 0 -2px 10px rgba(0,0,0,0.1);
z-index: 1000;
padding: 5px;
text-align: center;
}
.audio-controls {
display: flex;
justify-content: center;
align-items: center;
}
.audio-controls button {
border-radius: 50%;
margin: 0 5px;
}
.slider {
margin: 0 15px;
width: 450px;
}
.song-title {
margin-left: 10px;
}
@media (max-width: 768px) {
.current-time, .total-duration, .song-title {
display: none;
}
.slider {
width: 150px;
}
}
.volume-control {
display: none;
}
.audio-controls .btn-shuffle.active,
.audio-controls .btn-loop.active {
background-color: #007bff;
color: white;
}
</style>
</head>
<body>
<div class="container mt-5">
<h1 class="mb-4">YouTube Video List</h1>
<ul class="nav nav-pills mb-3" id="pills-tab" role="tablist">
<?php
$files = glob("list*.txt");
$categories = [];
foreach ($files as $index => $file) {
$lines = file($file, FILE_IGNORE_NEW_LINES);
if ($lines) {
$category = array_shift($lines);
$categories[$index] = $category;
$activeClass = ($index === 0) ? 'active' : '';
echo '<li class="nav-item">';
echo '<a class="nav-link ' . $activeClass . '" id="pills-' . $index . '-tab" data-toggle="pill" href="#pills-' . $index . '" role="tab" aria-controls="pills-' . $index . '" aria-selected="' . ($index === 0 ? 'true' : 'false') . '">' . htmlspecialchars($category) . '</a>';
echo '</li>';
}
}
?>
</ul>
<div class="tab-content" id="pills-tabContent">
<?php
foreach ($files as $index => $file) {
$activeClass = ($index === 0) ? 'show active' : '';
echo '<div class="tab-pane fade ' . $activeClass . '" id="pills-' . $index . '" role="tabpanel" aria-labelledby="pills-' . $index . '-tab">';
echo '<div class="row">';
$lines = file($file, FILE_IGNORE_NEW_LINES);
array_shift($lines); // Remove the category line
foreach ($lines as $line) {
$videoData = explode(",", trim($line));
$title = $videoData[0];
$url = $videoData[1];
parse_str(parse_url($url, PHP_URL_QUERY), $urlParams);
$videoId = $urlParams['v'];
$thumbnailUrl = "https://img.youtube.com/vi/$videoId/default.jpg";
echo '<div class="col-md-4 mb-4">';
echo '<div class="list-group-item">';
echo '<img src="' . $thumbnailUrl . '" class="thumbnail" alt="Thumbnail">';
echo '<div>' . htmlspecialchars($title) . '</div>';
echo '<i class="fas fa-play play-icon" data-video-id="' . $videoId . '"></i>';
echo '</div>';
echo '</div>';
}
echo '</div>';
echo '</div>';
}
?>
</div>
</div>
<div class="youtube-audio-player" id="audioPlayer">
<div id="player"></div>
<div class="audio-controls">
<span class="current-time" id="currentTime">0:00</span>
<button class="btn btn-secondary" id="prevButton"><i class="fas fa-step-backward"></i></button>
<button class="btn btn-primary" id="playPauseButton"><i class="fas fa-play"></i></button>
<input type="range" class="slider" id="seekSlider" value="0" step="1">
<button class="btn btn-secondary" id="nextButton"><i class="fas fa-step-forward"></i></button>
<button class="btn btn-secondary" id="volumeButton"><i class="fas fa-volume-up"></i></button>
<input type="range" class="slider volume-control" id="volumeSlider" value="100" step="1" min="0" max="100">
<button class="btn btn-secondary btn-shuffle" id="shuffleButton"><i class="fas fa-random"></i></button>
<button class="btn btn-secondary btn-loop" id="loopButton"><i class="fas fa-redo"></i></button>
<span class="total-duration" id="totalDuration">0:00</span>
<span class="song-title" id="songTitle"></span>
</div>
</div>
<!-- Bootstrap JS and dependencies -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<!-- YouTube IFrame API -->
<script src="https://www.youtube.com/iframe_api"></script>
<script>
var player;
var isPlaying = false;
var isShuffling = false;
var isLooping = false;
var videoList = [];
var currentVideoIndex = 0;
var sliderInterval;
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('.play-icon').forEach(icon => {
icon.addEventListener('click', function() {
var videoId = this.getAttribute('data-video-id');
currentVideoIndex = videoList.findIndex(video => video.id === videoId);
loadPlayer(videoId);
});
});
document.getElementById('prevButton').addEventListener('click', function() {
currentVideoIndex = (currentVideoIndex > 0) ? currentVideoIndex - 1 : videoList.length - 1;
loadPlayer(videoList[currentVideoIndex].id);
});
document.getElementById('nextButton').addEventListener('click', function() {
if (isShuffling) {
currentVideoIndex = Math.floor(Math.random() * videoList.length);
} else {
currentVideoIndex = (currentVideoIndex < videoList.length - 1) ? currentVideoIndex + 1 : 0;
}
loadPlayer(videoList[currentVideoIndex].id);
});
document.getElementById('volumeButton').addEventListener('click', function() {
var volumeControl = document.getElementById('volumeSlider');
volumeControl.style.display = volumeControl.style.display === 'none' ? 'block' : 'none';
});
document.getElementById('shuffleButton').addEventListener('click', function() {
isShuffling = !isShuffling;
this.classList.toggle('active');
});
document.getElementById('loopButton').addEventListener('click', function() {
isLooping = !isLooping;
this.classList.toggle('active');
});
// Load video list from PHP
<?php foreach ($files as $file) : ?>
<?php
$lines = file($file, FILE_IGNORE_NEW_LINES);
array_shift($lines); // Remove the category line
?>
<?php foreach ($lines as $line) : ?>
<?php
$videoData = explode(",", trim($line));
$title = $videoData[0];
$url = $videoData[1];
parse_str(parse_url($url, PHP_URL_QUERY), $urlParams);
$videoId = $urlParams['v'];
?>
videoList.push({ id: "<?php echo $videoId; ?>", title: "<?php echo htmlspecialchars($title); ?>" });
<?php endforeach; ?>
<?php endforeach; ?>
});
function onYouTubeIframeAPIReady() {
// Player setup handled on demand
}
function loadPlayer(videoId) {
if (player) {
player.loadVideoById(videoId);
} else {
player = new YT.Player('player', {
height: '0',
width: '0',
videoId: videoId,
playerVars: {
'autoplay': 0,
'controls': 0
},
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
document.getElementById('audioPlayer').style.display = 'block';
updateSongTitle(videoId);
}
function onPlayerReady(event) {
document.getElementById('playPauseButton').addEventListener('click', function() {
if (isPlaying) {
player.pauseVideo();
} else {
player.playVideo();
}
});
document.getElementById('seekSlider').addEventListener('input', function() {
var seekTo = player.getDuration() * (this.value / 100);
player.seekTo(seekTo, true);
});
document.getElementById('volumeSlider').addEventListener('input', function() {
player.setVolume(this.value);
});
}
function onPlayerStateChange(event) {
clearInterval(sliderInterval);
if (event.data == YT.PlayerState.PLAYING) {
isPlaying = true;
document.getElementById('playPauseButton').innerHTML = '<i class="fas fa-pause"></i>';
sliderInterval = setInterval(updateSlider, 1000);
} else {
isPlaying = false;
document.getElementById('playPauseButton').innerHTML = '<i class="fas fa-play"></i>';
}
if (event.data == YT.PlayerState.ENDED) {
if (isLooping) {
player.playVideo();
} else {
document.getElementById('nextButton').click();
}
}
}
function updateSlider() {
var seekSlider = document.getElementById('seekSlider');
var currentTime = player.getCurrentTime();
var duration = player.getDuration();
seekSlider.value = (currentTime / duration) * 100;
document.getElementById('currentTime').textContent = formatTime(currentTime);
document.getElementById('totalDuration').textContent = formatTime(duration);
}
function updateSongTitle(videoId) {
var song = videoList.find(video => video.id === videoId);
document.getElementById('songTitle').textContent = song ? song.title : '';
}
function formatTime(seconds) {
var minutes = Math.floor(seconds / 60);
var seconds = Math.floor(seconds % 60);
return minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
}
</script>
</body>
</html>
EP Note
PHP Bagian:
- Membaca setiap file
list*.txtdan mengambil kategori dari baris pertama setiap file. - Membuat tab dan konten tab secara dinamis berdasarkan file yang ditemukan.
- Menggunakan array
videoListuntuk menyimpan semua video dari semua file dan menginisialisasi JavaScript denganjson_encode.
- Membaca setiap file
HTML Bagian:
- Menggunakan tab dari Bootstrap untuk menampilkan kategori dan konten secara dinamis.
- Menambahkan ikon play untuk setiap video.
CSS Bagian:
- Menambahkan gaya untuk menampilkan kontrol audio dengan rapi dan sejajar.
- Menyembunyikan kontrol volume dan menambahkannya kembali saat tombol volume diklik.
JavaScript Bagian:
- Menambahkan fitur shuffle dan loop dengan mengatur event listeners untuk tombol shuffle dan loop.
- Menggunakan
updateSongTitleuntuk memperbarui judul lagu yang sedang diputar. - Memperbarui
updateSlideruntuk memperbarui slider dan waktu pemutaran.
Perubahan ini memastikan semua daftar dari list*.txt diambil dengan benar dan konten ditampilkan sesuai dengan kategorinya. Video player juga mendukung shuffle dan loop.
Audio Title