Skip to content

Instantly share code, notes, and snippets.

@s3va
Last active October 11, 2025 01:21
Show Gist options
  • Select an option

  • Save s3va/32e0d4d07dc88ce5d6f831f6945e8fbd to your computer and use it in GitHub Desktop.

Select an option

Save s3va/32e0d4d07dc88ce5d6f831f6945e8fbd to your computer and use it in GitHub Desktop.
audio player of oga files in html page my javascript in php
<?php
// $files = glob("*.oga");
$files = glob('*.{oga,mp3}', GLOB_BRACE);
sort($files);
function formatSize($bytes) {
if ($bytes >= 1048576) return number_format($bytes / 1048576, 2) . ' MB';
if ($bytes >= 1024) return number_format($bytes / 1024, 2) . ' KB';
return $bytes . ' bytes';
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>OGA Audio Player with Sizes and Label</title>
<style>
html { color-scheme: dark; }
body { font-family: Arial, sans-serif; margin: 20px; }
ul.playlist { list-style: none; padding: 0; max-width: 500px; }
ul.playlist li { cursor: pointer; padding: 5px 10px; border-bottom: 1px solid #ccc; display: flex; justify-content: space-between; }
ul.playlist li:hover { background: #404040; }
ul.playlist li.active { background: #007BFF; color: white; }
.filename { flex-grow: 1; }
.filesize { margin-left: 10px; font-size: 0.9em; white-space: nowrap; }
/*.filesize { margin-left: 10px; color: #666; font-size: 0.9em; white-space: nowrap; }*/
#currentPlaying { margin-bottom: 10px; font-weight: bold; }
</style>
</head>
<body>
<!-- .filesize { margin-left: 10px; color: #666; font-size: 0.9em; white-space: nowrap; } -->
<h2>OGA Files Playlist with Sizes</h2>
<ul class="playlist" id="playlist">
<?php foreach ($files as $index => $file): ?>
<li data-index="<?= $index ?>">
<span class="filename"><?= htmlspecialchars($file) ?></span>
<span class="filesize">(<?= formatSize(filesize($file)) ?>)</span>
</li>
<?php endforeach; ?>
</ul>
<div id="currentPlaying">No file playing</div>
<audio id="audioPlayer" controls preload="auto" style="width: 500px;">
Your browser does not support the audio element.
</audio>
<script>
const files = <?= json_encode($files) ?>;
const playlist = document.getElementById('playlist');
const audioPlayer = document.getElementById('audioPlayer');
const currentPlayingLabel = document.getElementById('currentPlaying');
let currentIndex = -1;
function formatSize(bytes) {
if (bytes >= 1048576) return (bytes / 1048576).toFixed(2) + ' MB';
if (bytes >= 1024) return (bytes / 1024).toFixed(2) + ' KB';
return bytes + ' bytes';
}
function updateCurrentPlaying(index) {
if (index < 0 || index >= files.length) {
currentPlayingLabel.textContent = 'No file playing';
return;
}
const file = files[index];
fetch(file, { method: 'HEAD' }).then(response => {
const size = response.headers.get('content-length');
currentPlayingLabel.textContent = `${file} (${formatSize(parseInt(size))})`;
}).catch(() => {
currentPlayingLabel.textContent = `${file} (size unknown)`;
});
}
function setActiveItem(index) {
Array.from(playlist.children).forEach((li, i) => {
li.classList.toggle('active', i === index);
});
}
function playFile(index) {
if (index < 0 || index >= files.length) return;
currentIndex = index;
audioPlayer.src = files[currentIndex];
audioPlayer.play();
setActiveItem(currentIndex);
updateCurrentPlaying(currentIndex);
}
playlist.addEventListener('click', e => {
const li = e.target.tagName === 'LI' ? e.target : e.target.closest('li');
if (!li) return;
const index = parseInt(li.getAttribute('data-index'), 10);
playFile(index);
});
audioPlayer.addEventListener('ended', () => {
if (currentIndex + 1 < files.length) {
playFile(currentIndex + 1);
} else {
currentPlayingLabel.textContent = 'No file playing';
setActiveItem(-1);
currentIndex = -1;
}
});
</script>
</body>
</html>
<?php
/**
* Dark-themed Directory Index
* Matches YYYYMMDD pattern and sorts by date
*/
// Dark theme CSS
$darkTheme = "
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: linear-gradient(135deg, #0c0c0c 0%, #1a1a1a 100%);
color: #e0e0e0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
background: rgba(30, 30, 30, 0.95);
border-radius: 15px;
border: 1px solid #333;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
/* overflow: hidden; */
}
.header {
background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%);
padding: 30px;
text-align: center;
border-bottom: 2px solid #444;
}
.header h1 {
color: #ffffff;
font-size: 2.5em;
margin-bottom: 10px;
text-shadow: 0 2px 4px rgba(0,0,0,0.5);
}
.header p {
color: #b0b0b0;
font-size: 1.1em;
}
.stats {
display: flex;
justify-content: center;
gap: 30px;
margin-top: 20px;
flex-wrap: wrap;
}
.stat-box {
background: rgba(40, 40, 40, 0.8);
padding: 15px 25px;
border-radius: 10px;
border: 1px solid #444;
text-align: center;
}
.stat-number {
font-size: 2em;
font-weight: bold;
color: #4fc3f7;
display: block;
}
.stat-label {
color: #888;
font-size: 0.9em;
}
.content {
padding: 30px;
}
.controls {
background: rgba(40, 40, 40, 0.6);
padding: 20px;
border-radius: 10px;
margin-bottom: 25px;
border: 1px solid #333;
}
.control-group {
display: flex;
gap: 15px;
align-items: center;
flex-wrap: wrap;
}
.btn {
background: linear-gradient(135deg, #4fc3f7 0%, #29b6f6 100%);
color: #000;
border: none;
padding: 10px 20px;
border-radius: 6px;
cursor: pointer;
font-weight: bold;
transition: all 0.3s ease;
text-decoration: none;
display: inline-block;
}
.btn:hover {
background: linear-gradient(135deg, #29b6f6 0%, #0288d1 100%);
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(41, 182, 246, 0.3);
}
.btn-secondary {
background: linear-gradient(135deg, #666 0%, #444 100%);
color: #fff;
}
.btn-secondary:hover {
background: linear-gradient(135deg, #777 0%, #555 100%);
}
.directory-table {
width: 100%;
border-collapse: collapse;
background: rgba(25, 25, 25, 0.8);
border-radius: 10px;
overflow: hidden;
border: 1px solid #333;
}
.directory-table th {
background: linear-gradient(135deg, #333 0%, #222 100%);
padding: 15px;
text-align: left;
color: #4fc3f7;
font-weight: 600;
border-bottom: 2px solid #444;
}
.directory-table td {
padding: 15px;
border-bottom: 1px solid #333;
transition: background 0.3s ease;
}
.directory-table td {
padding: 15px;
border-bottom: 1px solid #333;
transition: background 0.3s ease;
}
.directory-table tr:hover td {
background: rgba(60, 60, 60, 0.5);
}
.directory-table tr:last-child td {
border-bottom: none;
}
.directory-name {
color: #ffffff;
font-weight: bold;
font-family: 'Courier New', monospace;
font-size: 1.1em;
}
.date-info {
color: #b0b0b0;
}
.day-highlight {
color: #4fc3f7;
font-weight: bold;
}
.age-indicator {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 50%;
margin-right: 8px;
}
.age-recent { background: #4caf50; }
.age-medium { background: #ff9800; }
.age-old { background: #f44336; }
.empty-state {
text-align: center;
padding: 50px;
color: #888;
}
.empty-state i {
font-size: 3em;
margin-bottom: 20px;
display: block;
color: #444;
}
.footer {
text-align: center;
padding: 20px;
color: #666;
border-top: 1px solid #333;
background: rgba(20, 20, 20, 0.8);
}
.badge {
background: #4fc3f7;
color: #000;
padding: 3px 8px;
border-radius: 12px;
font-size: 0.8em;
font-weight: bold;
margin-left: 8px;
}
@media (max-width: 768px) {
.container {
margin: 10px;
border-radius: 10px;
}
.header h1 {
font-size: 2em;
}
.diectory-table {
font-size: 0.9em;
}
.control-group {
justify-content: center;
}
}
@media (max-width: 640px) {
body {
padding: 0px;
}
.directory-table hd {
padding-left: 0px;
padding-right: 0px;
}
.directory-table td {
padding-left: 0px;
padding-right: 0px;
}
.content {
padding: 0px;
}
}
</style>
";
// Function to get age indicator
function getAgeIndicator($date) {
$now = new DateTime();
$diff = $now->diff($date);
$days = $diff->days;
if ($days <= 7) return '<span class="age-indicator age-recent" title="Recent (≀ 7 days)"></span>';
if ($days <= 30) return '<span class="age-indicator age-medium" title="Medium (≀ 30 days)"></span>';
return '<span class="age-indicator age-old" title="Old (> 30 days)"></span>';
}
// Scan directories
$currentDir = '.';
$pattern = '/^\d{8}$/';
$matchedDirs = [];
$totalDirs = 0;
$validDirs = 0;
if ($handle = opendir($currentDir)) {
while (false !== ($entry = readdir($handle))) {
if( $entry !== '.' && $entry !== '..' && is_dir($entry) ){
$totalDirs++;
if ($entry !== '.' && $entry !== '..' && is_dir($entry) && preg_match($pattern, $entry)) {
$date = DateTime::createFromFormat('Ymd', $entry);
if ($date) {
$matchedDirs[] = [
'name' => $entry,
'date' => $date,
'formatted' => $date->format('Y-m-d'),
'day' => $date->format('l'),
'timestamp' => $date->getTimestamp()
];
$validDirs++;
}
}
}
}
closedir($handle);
}
// Sort by date (newest first)
usort($matchedDirs, function($a, $b) {
return $b['timestamp'] - $a['timestamp'];
});
// Get date range
$dateRange = 'N/A';
if (!empty($matchedDirs)) {
$oldest = end($matchedDirs);
$newest = reset($matchedDirs);
$dateRange = $oldest['formatted'] . ' to ' . $newest['formatted'];
}
// Output HTML
echo "<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<title>Directory Index - YYYYMMDD</title>
$darkTheme
</head>
<body>
<div class='container'>
<div class='header'>
<h1>πŸ“ Directory Index</h1>
<p>Directories matching YYYYMMDD date pattern</p>
<div class='stats'>
<div class='stat-box'>
<span class='stat-number'>$totalDirs</span>
<span class='stat-label'>Total Directories</span>
</div>
<div class='stat-box'>
<span class='stat-number'>$validDirs</span>
<span class='stat-label'>Date Pattern Matches</span>
</div>
<div class='stat-box'>
<span class='stat-number'>" . count($matchedDirs) . "</span>
<span class='stat-label'>Valid Dates</span>
</div>
<div class='stat-box'>
<span class='stat-number'>$dateRange</span>
<span class='stat-label'>Date Range</span>
</div>
</div>
</div>
<div class='content'>
<div class='controls'>
<div class='control-group'>
<button class='btn' onclick='location.reload()'>πŸ”„ Refresh</button>
<button class='btn btn-secondary' onclick='exportToFile()'>πŸ“₯ Export List</button>
<span style='color: #888; margin-left: auto;'>
" . date('Y-m-d H:i:s') . "
</span>
</div>
</div>";
if (empty($matchedDirs)) {
echo "<div class='empty-state'>
<i>πŸ“</i>
<h3>No directories found</h3>
<p>No directories matching the YYYYMMDD pattern were found in the current directory.</p>
</div>";
} else {
echo "<table class='directory-table'>
<thead>
<tr>
<th>Directory Name</th>
<th>Date</th>
<th>Day</th>
<th>Age</th>
<th>Actions</th>
</tr>
</thead>
<tbody>";
foreach ($matchedDirs as $dir) {
$ageIndicator = getAgeIndicator($dir['date']);
$daysAgo = $dir['date']->diff(new DateTime())->days;
$ageText = $daysAgo == 0 ? 'Today' : ($daysAgo == 1 ? '1 day ago' : "$daysAgo days ago");
echo "<tr>
<td>
<span class='directory-name'>πŸ“‚ {$dir['name']}</span>
</td>
<td class='date-info'>{$dir['formatted']}</td>
<td><span class='day-highlight'>{$dir['day']}</span></td>
<td class='date-info'>
$ageIndicator $ageText
</td>
<td>
<button class='btn btn-secondary' onclick=\"openDirectory('{$dir['name']}')\">
Open
</button>
</td>
</tr>";
}
echo "</tbody></table>";
}
echo " </div>
<div class='footer'>
<p>Generated by Directory Index β€’ " . count($matchedDirs) . " directories found β€’ Pattern: YYYYMMDD</p>
</div>
</div>
<script>
function openDirectory(dirName) {
if (confirm('Open directory: ' + dirName + '?')) {
window.open('./' + dirName, '_blank');
}
}
function exportToFile() {
const content = " . json_encode(array_map(function($dir) {
return [
'directory' => $dir['name'],
'date' => $dir['formatted'],
'day' => $dir['day']
];
}, $matchedDirs)) . ";
const blob = new Blob([JSON.stringify(content, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'directory-index-' + new Date().toISOString().split('T')[0] + '.json';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
// Add some interactive effects
document.addEventListener('DOMContentLoaded', function() {
const rows = document.querySelectorAll('.directory-table tr');
rows.forEach((row, index) => {
row.style.animationDelay = (index * 0.1) + 's';
});
});
</script>
</body>
</html>";
?>
<?php
/**
* Dark-themed Directory Index
* Matches YYYYMMDD pattern and sorts by date
*/
// Dark theme CSS
$darkTheme = "
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: linear-gradient(135deg, #0c0c0c 0%, #1a1a1a 100%);
color: #e0e0e0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
background: rgba(30, 30, 30, 0.95);
border-radius: 15px;
border: 1px solid #333;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
/* overflow: hidden; */
}
.header {
background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%);
padding: 30px;
text-align: center;
border-bottom: 2px solid #444;
}
.header h1 {
color: #ffffff;
font-size: 2.5em;
margin-bottom: 10px;
text-shadow: 0 2px 4px rgba(0,0,0,0.5);
}
.header p {
color: #b0b0b0;
font-size: 1.1em;
}
.stats {
display: flex;
justify-content: center;
gap: 30px;
margin-top: 20px;
flex-wrap: wrap;
}
.stat-box {
background: rgba(40, 40, 40, 0.8);
padding: 15px 25px;
border-radius: 10px;
border: 1px solid #444;
text-align: center;
}
.stat-number {
font-size: 2em;
font-weight: bold;
color: #4fc3f7;
display: block;
}
.stat-label {
color: #888;
font-size: 0.9em;
}
.content {
padding: 30px;
}
.controls {
background: rgba(40, 40, 40, 0.6);
padding: 20px;
border-radius: 10px;
margin-bottom: 25px;
border: 1px solid #333;
}
.control-group {
display: flex;
gap: 15px;
align-items: center;
flex-wrap: wrap;
}
.btn {
background: linear-gradient(135deg, #4fc3f7 0%, #29b6f6 100%);
color: #000;
border: none;
padding: 10px 20px;
border-radius: 6px;
cursor: pointer;
font-weight: bold;
transition: all 0.3s ease;
text-decoration: none;
display: inline-block;
}
.btn:hover {
background: linear-gradient(135deg, #29b6f6 0%, #0288d1 100%);
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(41, 182, 246, 0.3);
}
.btn-secondary {
background: linear-gradient(135deg, #666 0%, #444 100%);
color: #fff;
}
.btn-secondary:hover {
background: linear-gradient(135deg, #777 0%, #555 100%);
}
.directory-table {
width: 100%;
border-collapse: collapse;
background: rgba(25, 25, 25, 0.8);
border-radius: 10px;
overflow: hidden;
border: 1px solid #333;
}
.directory-table th {
background: linear-gradient(135deg, #333 0%, #222 100%);
padding: 15px;
text-align: left;
color: #4fc3f7;
font-weight: 600;
border-bottom: 2px solid #444;
}
.directory-table td {
padding: 15px;
border-bottom: 1px solid #333;
transition: background 0.3s ease;
}
.directory-table td {
padding: 15px;
border-bottom: 1px solid #333;
transition: background 0.3s ease;
}
.directory-table tr:hover td {
background: rgba(60, 60, 60, 0.5);
}
.directory-table tr:last-child td {
border-bottom: none;
}
.directory-name {
color: #ffffff;
font-weight: bold;
font-family: 'Courier New', monospace;
font-size: 1.1em;
}
.date-info {
color: #b0b0b0;
}
.day-highlight {
color: #4fc3f7;
font-weight: bold;
}
.age-indicator {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 50%;
margin-right: 8px;
}
.age-recent { background: #4caf50; }
.age-medium { background: #ff9800; }
.age-old { background: #f44336; }
.empty-state {
text-align: center;
padding: 50px;
color: #888;
}
.empty-state i {
font-size: 3em;
margin-bottom: 20px;
display: block;
color: #444;
}
.footer {
text-align: center;
padding: 20px;
color: #666;
border-top: 1px solid #333;
background: rgba(20, 20, 20, 0.8);
}
.badge {
background: #4fc3f7;
color: #000;
padding: 3px 8px;
border-radius: 12px;
font-size: 0.8em;
font-weight: bold;
margin-left: 8px;
}
@media (max-width: 768px) {
.container {
margin: 10px;
border-radius: 10px;
}
.header h1 {
font-size: 2em;
}
.diectory-table {
font-size: 0.9em;
}
.control-group {
justify-content: center;
}
}
@media (max-width: 640px) {
body {
padding: 0px;
}
.directory-table hd {
padding-left: 0px;
padding-right: 0px;
}
.directory-table td {
padding-left: 0px;
padding-right: 0px;
}
.content {
padding: 0px;
}
}
</style>
";
// Function to get age indicator
function getAgeIndicator($date) {
$now = new DateTime();
$diff = $now->diff($date);
$days = $diff->days;
if ($days <= 7) return '<span class="age-indicator age-recent" title="Recent (≀ 7 days)"></span>';
if ($days <= 30) return '<span class="age-indicator age-medium" title="Medium (≀ 30 days)"></span>';
return '<span class="age-indicator age-old" title="Old (> 30 days)"></span>';
}
// Scan directories
$currentDir = '.';
$pattern = '/^\d{8}$/';
$matchedDirs = [];
$totalDirs = 0;
$validDirs = 0;
if ($handle = opendir($currentDir)) {
while (false !== ($entry = readdir($handle))) {
if( $entry !== '.' && $entry !== '..' && is_dir($entry) ){
$totalDirs++;
if ($entry !== '.' && $entry !== '..' && is_dir($entry) && preg_match($pattern, $entry)) {
$date = DateTime::createFromFormat('Ymd', $entry);
if ($date) {
$matchedDirs[] = [
'name' => $entry,
'date' => $date,
'formatted' => $date->format('Y-m-d'),
'day' => $date->format('l'),
'timestamp' => $date->getTimestamp()
];
$validDirs++;
}
}
}
}
closedir($handle);
}
// Sort by date (newest first)
usort($matchedDirs, function($a, $b) {
return $b['timestamp'] - $a['timestamp'];
});
// Get date range
$dateRange = 'N/A';
if (!empty($matchedDirs)) {
$oldest = end($matchedDirs);
$newest = reset($matchedDirs);
$dateRange = $oldest['formatted'] . ' to ' . $newest['formatted'];
}
// Output HTML
echo "<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<title>Directory Index - YYYYMMDD</title>
$darkTheme
</head>
<body>
<div class='container'>
<div class='header'>
<h1>πŸ“ Directory Index</h1>
<p>Directories matching YYYYMMDD date pattern</p>
<div class='stats'>
<div class='stat-box'>
<span class='stat-number'>$totalDirs</span>
<span class='stat-label'>Total Directories</span>
</div>
<div class='stat-box'>
<span class='stat-number'>$validDirs</span>
<span class='stat-label'>Date Pattern Matches</span>
</div>
<div class='stat-box'>
<span class='stat-number'>" . count($matchedDirs) . "</span>
<span class='stat-label'>Valid Dates</span>
</div>
<div class='stat-box'>
<span class='stat-number'>$dateRange</span>
<span class='stat-label'>Date Range</span>
</div>
</div>
</div>
<div class='content'>
<div class='controls'>
<div class='control-group'>
<button class='btn' onclick='location.reload()'>πŸ”„ Refresh</button>
<button class='btn btn-secondary' onclick='exportToFile()'>πŸ“₯ Export List</button>
<span style='color: #888; margin-left: auto;'>
" . date('Y-m-d H:i:s') . "
</span>
</div>
</div>";
if (empty($matchedDirs)) {
echo "<div class='empty-state'>
<i>πŸ“</i>
<h3>No directories found</h3>
<p>No directories matching the YYYYMMDD pattern were found in the current directory.</p>
</div>";
} else {
echo "<table class='directory-table'>
<thead>
<tr>
<th>Directory Name</th>
<th>Date</th>
<th>Day</th>
<th>Age</th>
<th>Actions</th>
</tr>
</thead>
<tbody>";
foreach ($matchedDirs as $dir) {
$ageIndicator = getAgeIndicator($dir['date']);
$daysAgo = $dir['date']->diff(new DateTime())->days;
$ageText = $daysAgo == 0 ? 'Today' : ($daysAgo == 1 ? '1 day ago' : "$daysAgo days ago");
echo "<tr>
<td>
<span class='directory-name'>πŸ“‚ {$dir['name']}</span>
</td>
<td class='date-info'>{$dir['formatted']}</td>
<td><span class='day-highlight'>{$dir['day']}</span></td>
<td class='date-info'>
$ageIndicator $ageText
</td>
<td>
<button class='btn btn-secondary' onclick=\"openDirectory('{$dir['name']}')\">
Open
</button>
</td>
</tr>";
}
echo "</tbody></table>";
}
echo " </div>
<div class='footer'>
<p>Generated by Directory Index β€’ " . count($matchedDirs) . " directories found β€’ Pattern: YYYYMMDD</p>
</div>
</div>
<script>
function openDirectory(dirName) {
if (confirm('Open directory: ' + dirName + '?')) {
window.open('./' + dirName, '_blank');
}
}
function exportToFile() {
const content = " . json_encode(array_map(function($dir) {
return [
'directory' => $dir['name'],
'date' => $dir['formatted'],
'day' => $dir['day']
];
}, $matchedDirs)) . ";
const blob = new Blob([JSON.stringify(content, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'directory-index-' + new Date().toISOString().split('T')[0] + '.json';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
// Add some interactive effects
document.addEventListener('DOMContentLoaded', function() {
const rows = document.querySelectorAll('.directory-table tr');
rows.forEach((row, index) => {
row.style.animationDelay = (index * 0.1) + 's';
});
});
</script>
</body>
</html>";
?>
<?php
// Get all mp4 files in current directory
$mp4files = array_filter(scandir('.'), function($file) {
return is_file($file) && strtolower(pathinfo($file, PATHINFO_EXTENSION)) === 'mp4';
});
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>MP4 Video Player</title>
<style>
html { color-scheme: dark; }
body {
font-family: Arial, sans-serif;
margin: 20px;
}
#videoPlayer {
width: 100%;
max-width: 800px;
height: auto;
background: black;
}
#fileList {
margin-top: 20px;
max-width: 800px;
}
#fileList button {
display: block;
width: 100%;
padding: 10px;
margin: 5px 0;
font-size: 1rem;
text-align: left;
cursor: pointer;
border: 1px solid #ccc;
/* background: #f7f7f7;*/
}
#fileList button:hover {
/* background: #e2e2e2;*/
}
</style>
</head>
<body>
<h1>MP4 Video Player</h1>
<video id="videoPlayer" controls>
<source src="" type="video/mp4" />
Your browser does not support the video tag.
</video>
<div id="fileList">
<h2>Available Videos</h2>
<?php if (empty($mp4files)): ?>
<p>No MP4 files found in this directory.</p>
<?php else: ?>
<?php foreach ($mp4files as $file): ?>
<button type="button" onclick="loadVideo('<?= htmlspecialchars($file, ENT_QUOTES) ?>')">
<?= htmlspecialchars($file) ?>
</button>
<?php endforeach; ?>
<?php endif; ?>
</div>
<script>
function loadVideo(filename) {
const video = document.getElementById('videoPlayer');
// Change video source
video.src = filename;
video.load();
video.play();
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment