fix filmstrip: use hls.js for HLS stream frame capture, not only direct streams

This commit is contained in:
Zac Gaetano 2026-05-25 09:30:40 -04:00
parent b345f5f6a4
commit 37c406bf4d

View file

@ -78,9 +78,9 @@ function AssetDetail({ asset, onClose }) {
return function() { hls.destroy(); }; return function() { hls.destroy(); };
}, [streamUrl, streamType]); }, [streamUrl, streamType]);
// Build filmstrip from real video when browser-playable media exists. // Build filmstrip from real video frames. HLS streams use hls.js probe.
React.useEffect(() => { React.useEffect(() => {
if (!streamUrl || totalMs <= 0 || streamType === 'hls') { if (!streamUrl || totalMs <= 0) {
setFilmFrames([]); setFilmFrames([]);
setFilmstripLoading(false); setFilmstripLoading(false);
return; return;
@ -94,11 +94,25 @@ function AssetDetail({ asset, onClose }) {
probe.muted = true; probe.muted = true;
probe.playsInline = true; probe.playsInline = true;
probe.preload = 'auto'; probe.preload = 'auto';
probe.src = streamUrl; if (streamType === 'hls') {
await new Promise(function(resolve, reject) { if (!window.Hls) throw new Error('hls.js not loaded');
probe.onloadedmetadata = resolve; await new Promise(function(resolve, reject) {
probe.onerror = reject; const hls = new window.Hls();
}); hls.on(window.Hls.Events.MANIFEST_PARSED, function() {
probe.oncanplay = function() { probe.oncanplay = null; resolve(); };
probe.onerror = reject;
});
hls.on(window.Hls.Events.ERROR, function(ev, data) { reject(data); });
hls.loadSource(streamUrl);
hls.attachMedia(probe);
});
} else {
probe.src = streamUrl;
await new Promise(function(resolve, reject) {
probe.onloadedmetadata = resolve;
probe.onerror = reject;
});
}
const frameCount = 28; const frameCount = 28;
const width = 160; const width = 160;
const height = 90; const height = 90;
@ -721,4 +735,4 @@ function avatarColor(initials) {
return 'linear-gradient(135deg, hsl(' + (h % 360) + ' 60% 50%), hsl(' + ((h + 60) % 360) + ' 60% 45%))'; return 'linear-gradient(135deg, hsl(' + (h % 360) + ' 60% 50%), hsl(' + ((h + 60) % 360) + ' 60% 45%))';
} }
Object.assign(window, { AssetDetail, msToTimecode, parseDuration, avatarColor }); Object.assign(window, { AssetDetail, msToTimecode, parseDuration, avatarColor });