live stream support
This commit is contained in:
@@ -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>` : ''}
|
||||
|
||||
Reference in New Issue
Block a user