HLS playback enhancements

This commit is contained in:
2025-07-30 08:58:18 -04:00
parent 172b43fc8b
commit bde9fda78f

View File

@@ -54,7 +54,7 @@ export function Player() {
const lcStation = activeStation.toLowerCase(); const lcStation = activeStation.toLowerCase();
const streamUrl = `https://stream.codey.lol/hls/${lcStation}/${lcStation}.m3u8?t=${Date.now()}`; const streamUrl = `https://stream.codey.lol/hls/${lcStation}/${lcStation}.m3u8?t=${Date.now()}`;
// Cleanup existing stream // Cleanup
if (hlsRef.current) { if (hlsRef.current) {
hlsRef.current.destroy(); hlsRef.current.destroy();
hlsRef.current = null; hlsRef.current = null;
@@ -64,37 +64,78 @@ export function Player() {
if (!audio) return; if (!audio) return;
if (audio.canPlayType("application/vnd.apple.mpegurl")) { if (audio.canPlayType("application/vnd.apple.mpegurl")) {
// Native support (Safari)
audio.src = streamUrl; audio.src = streamUrl;
audio.load();
audio.play().then(() => setIsPlaying(true)).catch(console.error); audio.play().then(() => setIsPlaying(true)).catch(console.error);
} else if (Hls.isSupported()) { return;
}
if (!Hls.isSupported()) {
console.error("HLS not supported");
return;
}
const hls = new Hls({ const hls = new Hls({
maxBufferLength: 30, maxBufferLength: 30,
maxMaxBufferLength: 60, maxMaxBufferLength: 60,
abrEwmaFastLive: 2.0,
abrEwmaSlowLive: 6.0,
abrBandWidthFactor: 0.95, // Bias toward higher quality
autoStartLoad: true, autoStartLoad: true,
startLevel: -1, // adaptive start startLevel: -1,
}); });
hls.loadSource(streamUrl);
hls.attachMedia(audio); hls.attachMedia(audio);
hls.on(Hls.Events.ERROR, (_, data) => { hls.on(Hls.Events.MEDIA_ATTACHED, () => {
hls.loadSource(streamUrl);
});
hls.on(Hls.Events.MANIFEST_PARSED, () => {
audio.play().then(() => setIsPlaying(true)).catch(console.error);
});
hls.on(Hls.Events.ERROR, (event, data) => {
console.warn("HLS error:", data);
if (data.fatal) { if (data.fatal) {
console.error("HLS fatal error:", data); switch (data.type) {
case Hls.ErrorTypes.NETWORK_ERROR:
case Hls.ErrorTypes.MEDIA_ERROR:
case Hls.ErrorTypes.OTHER_ERROR:
console.error("Fatal HLS error, attempting recovery…");
try {
hls.destroy(); hls.destroy();
hlsRef.current = null;
setIsPlaying(false);
// Delay before trying to reconnect
setTimeout(() => {
playStream();
}, 3000);
} catch (e) {
console.error("HLS recovery failed:", e);
}
break;
default:
hls.destroy();
hlsRef.current = null;
setIsPlaying(false);
}
} }
}); });
hlsRef.current = hls; hlsRef.current = hls;
audio.play().then(() => setIsPlaying(true)).catch(console.error);
} else {
console.error("HLS not supported");
}
}; };
useEffect(() => {
const interval = setInterval(() => {
const audio = audioRef.current;
if (audio && isPlaying && audio.readyState < 2) {
console.warn("Playback seems stalled. Reloading stream.");
playStream();
}
}, 15000); // Check every 15 seconds
return () => clearInterval(interval);
}, [isPlaying]);
const togglePlayback = () => { const togglePlayback = () => {
const audio = audioRef.current; const audio = audioRef.current;
if (!audio) return; if (!audio) return;