Cache video metadata by mtime

This commit is contained in:
hbrain 2026-05-25 18:46:14 +02:00
parent 9e6f353271
commit 92290786b2
2 changed files with 30 additions and 1 deletions

1
.gitignore vendored
View file

@ -3,3 +3,4 @@ in-dir/
out-dir/ out-dir/
thumbs/ thumbs/
*.log *.log
cache/

View file

@ -1,6 +1,7 @@
<?php <?php
$config = require __DIR__ . "/config.php"; $config = require __DIR__ . "/config.php";
foreach (["videos_dir", "thumbs_dir", "uploads_dir"] as $d) if (!is_dir($config[$d])) mkdir($config[$d], 0775, true); foreach (["videos_dir", "thumbs_dir", "uploads_dir"] as $d) if (!is_dir($config[$d])) mkdir($config[$d], 0775, true);
if (!is_dir(__DIR__ . "/cache")) mkdir(__DIR__ . "/cache", 0775, true);
function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, "UTF-8"); } function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, "UTF-8"); }
function nice_title($s){ return trim(ucwords(str_replace(['_','-'], ' ', $s))); } function nice_title($s){ return trim(ucwords(str_replace(['_','-'], ' ', $s))); }
function video_metadata($path){ function video_metadata($path){
@ -44,14 +45,41 @@ function video_metadata($path){
} }
return $meta; return $meta;
} }
function load_video_cache($videos){
$cacheFile = __DIR__ . '/cache/videos.json';
$cache = is_file($cacheFile) ? json_decode((string)file_get_contents($cacheFile), true) : [];
if (!is_array($cache)) $cache = [];
$items = $cache['items'] ?? [];
$newItems = [];
$changed = false;
foreach ($videos as $path) {
$key = basename($path);
$mtime = filemtime($path);
$size = filesize($path);
$cached = $items[$key] ?? null;
if (!is_array($cached) || ($cached['mtime'] ?? null) !== $mtime || ($cached['size'] ?? null) !== $size) {
$cached = ['mtime' => $mtime, 'size' => $size, 'metadata' => video_metadata($path)];
$changed = true;
}
$newItems[$key] = $cached;
}
if (array_diff(array_keys($items), array_keys($newItems))) $changed = true;
if ($changed) {
file_put_contents($cacheFile, json_encode(['generated_at' => date('c'), 'items' => $newItems], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT), LOCK_EX);
}
return $newItems;
}
$videos = glob($config['videos_dir'].'/*.{mp4,webm,mov,m4v}', GLOB_BRACE) ?: []; $videos = glob($config['videos_dir'].'/*.{mp4,webm,mov,m4v}', GLOB_BRACE) ?: [];
usort($videos, fn($a,$b)=>filemtime($b)<=>filemtime($a)); usort($videos, fn($a,$b)=>filemtime($b)<=>filemtime($a));
$videoCache = load_video_cache($videos);
$page=max(1,(int)($_GET['page']??1)); $per=$config['items_per_page']; $total=count($videos); $pages=max(1,(int)ceil($total/$per)); $page=min($page,$pages); $slice=array_slice($videos,($page-1)*$per,$per); $page=max(1,(int)($_GET['page']??1)); $per=$config['items_per_page']; $total=count($videos); $pages=max(1,(int)ceil($total/$per)); $page=min($page,$pages); $slice=array_slice($videos,($page-1)*$per,$per);
?> ?>
<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>MVLog</title><link rel="stylesheet" href="style.css"></head><body> <!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>MVLog</title><link rel="stylesheet" href="style.css"></head><body>
<header><h1>MVLog</h1></header><main> <header><h1>MVLog</h1></header><main>
<section id="videos"><?php if(!$slice): ?><p>No videos yet.</p><?php endif; ?><div class="video-list"> <section id="videos"><?php if(!$slice): ?><p>No videos yet.</p><?php endif; ?><div class="video-list">
<?php foreach($slice as $v): $name=basename($v); $url=$config['public_videos'].'/'.rawurlencode($name); $size=filesize($v); $m=video_metadata($v); ?> <?php foreach($slice as $v): $name=basename($v); $url=$config['public_videos'].'/'.rawurlencode($name); $size=filesize($v); $m=$videoCache[$name]['metadata'] ?? video_metadata($v); ?>
<article class="video-row"><video controls preload="metadata" src="<?=h($url)?>"></video><div class="video-info"><h2><?=h($m['title'])?></h2><p class="meta"><span><?=h($m['date'])?></span><?php if($m['location']): ?><span><?=h($m['location'])?></span><?php endif; ?></p><?php if($m['description']): ?><p class="description"><?=h($m['description'])?></p><?php endif; ?><p class="details"><?=h(round($size/1048576,1))?> MB</p></div></article> <article class="video-row"><video controls preload="metadata" src="<?=h($url)?>"></video><div class="video-info"><h2><?=h($m['title'])?></h2><p class="meta"><span><?=h($m['date'])?></span><?php if($m['location']): ?><span><?=h($m['location'])?></span><?php endif; ?></p><?php if($m['description']): ?><p class="description"><?=h($m['description'])?></p><?php endif; ?><p class="details"><?=h(round($size/1048576,1))?> MB</p></div></article>
<?php endforeach; ?></div><div class="pages"><?php for($i=1;$i<=$pages;$i++): ?><a class="<?=$i===$page?'active':''?>" href="?page=<?=$i?>"><?=$i?></a><?php endfor; ?></div></section> <?php endforeach; ?></div><div class="pages"><?php for($i=1;$i<=$pages;$i++): ?><a class="<?=$i===$page?'active':''?>" href="?page=<?=$i?>"><?=$i?></a><?php endfor; ?></div></section>
</main><footer>Bubulescu.Org</footer></body></html> </main><footer>Bubulescu.Org</footer></body></html>