qhkr2z22o: Prefer direct mp4Url for feed video playback with hls fallback
This commit is contained in:
+22
-5
@@ -7,6 +7,8 @@ export interface CardMedia {
|
||||
src: string | null;
|
||||
/** Mux HLS playlist (videos only). Null when the video is not ready yet. */
|
||||
hlsUrl?: string | null;
|
||||
/** Direct progressive MP4 on the feed CDN (videos only). Preferred for playback. */
|
||||
mp4Url?: string | null;
|
||||
}
|
||||
|
||||
export interface CardPost {
|
||||
@@ -65,6 +67,18 @@ export function muxHlsUrl(v: unknown): string | null {
|
||||
}
|
||||
}
|
||||
|
||||
/** The MP4 URL only when it is https on the feed CDN. */
|
||||
export function feedMp4Url(v: unknown): string | null {
|
||||
const s = str(v);
|
||||
if (!s) return null;
|
||||
try {
|
||||
const u = new URL(s);
|
||||
return u.protocol === "https:" && u.hostname === "cdn.feed.sharedservices.vt.com" ? s : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function toMedia(raw: unknown): CardMedia[] {
|
||||
if (!Array.isArray(raw)) return [];
|
||||
const items = raw
|
||||
@@ -76,8 +90,9 @@ function toMedia(raw: unknown): CardMedia[] {
|
||||
if (m.mediaType === "video") {
|
||||
const thumb = str(m.thumbnailUrl);
|
||||
const hls = muxHlsUrl(m.hlsUrl);
|
||||
// Keep a video even with no thumbnail or hlsUrl yet (just published).
|
||||
out.push({ kind: "video", src: thumb, hlsUrl: hls });
|
||||
const mp4 = feedMp4Url(m.mp4Url);
|
||||
// Keep a video even with no thumbnail or playable URL yet (just published).
|
||||
out.push({ kind: "video", src: thumb, hlsUrl: hls, mp4Url: mp4 });
|
||||
continue;
|
||||
}
|
||||
const src = str(m.imageMediumWebpUrl) ?? str(m.imageMediumUrl) ?? str(m.imageUrl);
|
||||
@@ -143,10 +158,12 @@ export function mergePosts(...lists: CardPost[][]): CardPost[] {
|
||||
return sortByPublishedDesc(all);
|
||||
}
|
||||
|
||||
const hasHls = (p: CardPost) => p.media.some((m) => m.kind === "video" && m.hlsUrl);
|
||||
/** A video is playable once it has an mp4Url or an hlsUrl. */
|
||||
export const isPlayableVideo = (m: CardMedia) => m.kind === "video" && !!(m.mp4Url || m.hlsUrl);
|
||||
const hasPlayable = (p: CardPost) => p.media.some(isPlayableVideo);
|
||||
|
||||
/**
|
||||
* Swap in the media of shown posts whose video gained an hlsUrl on a refresh
|
||||
* Swap in the media of shown posts whose video gained an mp4Url or hlsUrl on a refresh
|
||||
* (transcoding finished), so the thumbnail upgrades to the player in place.
|
||||
* Returns the same array when nothing changed.
|
||||
*/
|
||||
@@ -155,7 +172,7 @@ export function upgradeVideos(current: CardPost[], fresh: CardPost[]): CardPost[
|
||||
let changed = false;
|
||||
const next = current.map((p) => {
|
||||
const f = byKey.get(p.key);
|
||||
if (f && !hasHls(p) && hasHls(f)) {
|
||||
if (f && !hasPlayable(p) && hasPlayable(f)) {
|
||||
changed = true;
|
||||
return { ...p, media: f.media };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user