fix HLS streaming quality
This commit is contained in:
@@ -54,45 +54,64 @@ 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
|
||||||
if (hlsRef.current) {
|
if (hlsRef.current) {
|
||||||
hlsRef.current.destroy();
|
hlsRef.current.destroy();
|
||||||
hlsRef.current = null;
|
hlsRef.current = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (audioRef.current.canPlayType("application/vnd.apple.mpegurl")) {
|
const audio = audioRef.current;
|
||||||
// Native HLS support (Safari)
|
if (!audio) return;
|
||||||
audioRef.current.src = streamUrl;
|
|
||||||
|
if (audio.canPlayType("application/vnd.apple.mpegurl")) {
|
||||||
|
// Native support (Safari)
|
||||||
|
audio.src = streamUrl;
|
||||||
|
audio.play().then(() => setIsPlaying(true)).catch(console.error);
|
||||||
} else if (Hls.isSupported()) {
|
} else if (Hls.isSupported()) {
|
||||||
const hls = new Hls({
|
const hls = new Hls({
|
||||||
maxBufferLength: 60,
|
maxBufferLength: 30,
|
||||||
|
maxMaxBufferLength: 60,
|
||||||
|
abrEwmaFastLive: 2.0,
|
||||||
|
abrEwmaSlowLive: 6.0,
|
||||||
|
abrBandWidthFactor: 0.95, // Bias toward higher quality
|
||||||
|
autoStartLoad: true,
|
||||||
|
startLevel: -1, // adaptive start
|
||||||
});
|
});
|
||||||
hls.loadSource(streamUrl);
|
|
||||||
hls.attachMedia(audioRef.current);
|
|
||||||
hlsRef.current = hls;
|
|
||||||
} else {
|
|
||||||
console.error("HLS is not supported in this browser.");
|
|
||||||
}
|
|
||||||
|
|
||||||
audioRef.current.play().then(() => setIsPlaying(true)).catch((e) => {
|
hls.loadSource(streamUrl);
|
||||||
console.error("Playback failed:", e);
|
hls.attachMedia(audio);
|
||||||
|
|
||||||
|
hls.on(Hls.Events.ERROR, (_, data) => {
|
||||||
|
if (data.fatal) {
|
||||||
|
console.error("HLS fatal error:", data);
|
||||||
|
hls.destroy();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
hlsRef.current = hls;
|
||||||
|
audio.play().then(() => setIsPlaying(true)).catch(console.error);
|
||||||
|
} else {
|
||||||
|
console.error("HLS not supported");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const togglePlayback = () => {
|
const togglePlayback = () => {
|
||||||
if (!audioRef.current) return;
|
const audio = audioRef.current;
|
||||||
|
if (!audio) return;
|
||||||
|
|
||||||
if (isPlaying) {
|
if (isPlaying) {
|
||||||
audioRef.current.pause();
|
audio.pause();
|
||||||
setIsPlaying(false);
|
setIsPlaying(false);
|
||||||
} else {
|
} else {
|
||||||
audioRef.current.play().then(() => setIsPlaying(true));
|
audio.play().then(() => setIsPlaying(true)).catch(console.error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (audioRef.current) {
|
const audio = audioRef.current;
|
||||||
audioRef.current.pause();
|
if (audio) {
|
||||||
audioRef.current.src = "";
|
audio.pause();
|
||||||
|
audio.src = "";
|
||||||
setIsPlaying(false);
|
setIsPlaying(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,6 +120,7 @@ export function Player() {
|
|||||||
return () => {
|
return () => {
|
||||||
if (hlsRef.current) {
|
if (hlsRef.current) {
|
||||||
hlsRef.current.destroy();
|
hlsRef.current.destroy();
|
||||||
|
hlsRef.current = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [activeStation]);
|
}, [activeStation]);
|
||||||
@@ -196,9 +216,7 @@ export function Player() {
|
|||||||
<div className="c-containter">
|
<div className="c-containter">
|
||||||
<div className="music-container mt-8">
|
<div className="music-container mt-8">
|
||||||
<section className="album-cover">
|
<section className="album-cover">
|
||||||
<div className="music-player__album" title="Album">
|
<div className="music-player__album" title="Album">{trackAlbum}</div>
|
||||||
{trackAlbum}
|
|
||||||
</div>
|
|
||||||
<img
|
<img
|
||||||
src={coverArt}
|
src={coverArt}
|
||||||
className="cover"
|
className="cover"
|
||||||
@@ -215,7 +233,7 @@ export function Player() {
|
|||||||
|
|
||||||
<div className="music-time">
|
<div className="music-time">
|
||||||
<p className="music-time__current">{formatTime(elapsed)}</p>
|
<p className="music-time__current">{formatTime(elapsed)}</p>
|
||||||
<p className="music-time__last">{formatTime(duration - elapsed)}</p>
|
<p className="music-time__last">{formatTime(remaining)}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="w-full h-2 rounded bg-neutral-300 dark:bg-neutral-700 overflow-hidden">
|
<div className="w-full h-2 rounded bg-neutral-300 dark:bg-neutral-700 overflow-hidden">
|
||||||
@@ -228,7 +246,6 @@ export function Player() {
|
|||||||
<div className="music-control">
|
<div className="music-control">
|
||||||
<div
|
<div
|
||||||
className="music-control__play"
|
className="music-control__play"
|
||||||
id="play"
|
|
||||||
onClick={togglePlayback}
|
onClick={togglePlayback}
|
||||||
role="button"
|
role="button"
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
|
Reference in New Issue
Block a user