live stream support

This commit is contained in:
Simon
2026-06-22 12:34:47 +00:00
parent a97f7e7b0f
commit b5b3e13dd0
9 changed files with 271 additions and 35 deletions

View File

@@ -138,31 +138,55 @@ App.feed = App.feed || {};
if (!resolved.url) return;
const refererParam = resolved.referer ? `&referer=${encodeURIComponent(resolved.referer)}` : '';
const userAgentParam = resolved.userAgent ? `&User-Agent=${encodeURIComponent(resolved.userAgent)}` : '';
const streamUrl = `/api/stream?url=${encodeURIComponent(resolved.url)}${refererParam}${userAgentParam}`;
const isHls = /\.m3u8($|\?)/i.test(resolved.url);
const canUseHls = !!(window.Hls && window.Hls.isSupported());
const liveParam = resolved.isLive ? '&live=1' : '';
const streamUrl = `/api/stream?url=${encodeURIComponent(resolved.url)}${refererParam}${userAgentParam}${liveParam}`;
const isHls = resolved.isLive ? true : /\.m3u8($|\?)/i.test(resolved.url);
video.muted = state.feedMuted;
video.preload = 'auto';
if (isHls && canUseHls) {
const hls = new window.Hls();
const startPlay = () => {
if (!autoplay) return;
const playPromise = video.play();
if (playPromise && typeof playPromise.catch === 'function') playPromise.catch(() => {});
};
const attachHls = (HlsLib) => {
const hls = new HlsLib();
video._hlsPlayer = hls;
hls.loadSource(streamUrl);
hls.attachMedia(video);
hls.on(window.Hls.Events.ERROR, (event, data) => {
hls.on(HlsLib.Events.ERROR, (event, data) => {
if (data && data.fatal && video._hlsPlayer === hls) {
hls.destroy();
video._hlsPlayer = null;
}
});
} else {
startPlay();
};
const startNative = () => {
video.src = streamUrl;
startPlay();
};
if (!isHls) {
startNative();
return;
}
if (autoplay) {
const playPromise = video.play();
if (playPromise && typeof playPromise.catch === 'function') playPromise.catch(() => {});
if (window.Hls && window.Hls.isSupported()) {
attachHls(window.Hls);
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
startNative();
} else {
// Lazy-load hls.js on demand for the first HLS slide.
App.ensureHls()
.then((HlsLib) => {
if (HlsLib && HlsLib.isSupported()) attachHls(HlsLib);
else startNative();
})
.catch(startNative);
}
};
@@ -177,15 +201,17 @@ App.feed = App.feed || {};
if (!scroller) return null;
const slide = document.createElement('div');
slide.className = 'feed-slide';
slide.className = v.isLive ? 'feed-slide is-live' : 'feed-slide';
slide.dataset.videoId = v.id;
slide.dataset.index = String(index);
slide._videoData = v;
slide._index = index;
const uploaderText = v.uploader || '';
const liveBadge = v.isLive ? '<span class="live-badge feed-live-badge">● LIVE</span>' : '';
slide.innerHTML = `
<img class="feed-poster" src="${v.thumb || ''}" alt="">
<img class="feed-poster" src="${v.thumb || ''}" alt="" loading="lazy" decoding="async">
<video class="feed-video" muted playsinline webkit-playsinline loop preload="none"></video>
${liveBadge}
<div class="feed-info">
<h4 class="feed-title">${v.title || ''}</h4>
${uploaderText ? `<p class="feed-uploader">${uploaderText}</p>` : ''}