fix: use playback selector in MediaPanel
This commit is contained in:
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
|
|
||||||
|
import { pickVideoPlaybackVariant } from "../lib/playback";
|
||||||
|
|
||||||
type Asset = {
|
type Asset = {
|
||||||
id: string;
|
id: string;
|
||||||
media_type: "image" | "video";
|
media_type: "image" | "video";
|
||||||
@@ -25,6 +27,7 @@ type SignedUrlResponse = {
|
|||||||
|
|
||||||
type PreviewUrlState = Record<string, string | undefined>;
|
type PreviewUrlState = Record<string, string | undefined>;
|
||||||
type VideoPlaybackVariant = { kind: "original" } | { kind: "video_mp4"; size: 720 };
|
type VideoPlaybackVariant = { kind: "original" } | { kind: "video_mp4"; size: 720 };
|
||||||
|
type VariantsResponse = Array<{ kind: string; size: number; key: string }>;
|
||||||
|
|
||||||
function startOfDayUtc(iso: string) {
|
function startOfDayUtc(iso: string) {
|
||||||
const d = new Date(iso);
|
const d = new Date(iso);
|
||||||
@@ -125,12 +128,32 @@ export function MediaPanel(props: { selectedDayIso: string | null }) {
|
|||||||
assetId: string,
|
assetId: string,
|
||||||
): Promise<{ url: string; variant: VideoPlaybackVariant }> {
|
): Promise<{ url: string; variant: VideoPlaybackVariant }> {
|
||||||
try {
|
try {
|
||||||
const url = await loadSignedUrl(assetId, "video_mp4_720");
|
const res = await fetch(`/api/assets/${assetId}/variants`, {
|
||||||
return { url, variant: { kind: "video_mp4", size: 720 } };
|
cache: "no-store",
|
||||||
|
});
|
||||||
|
if (!res.ok) throw new Error(`variants_fetch_failed:${res.status}`);
|
||||||
|
const variants = (await res.json()) as VariantsResponse;
|
||||||
|
const picked = pickVideoPlaybackVariant({
|
||||||
|
originalMimeType: null,
|
||||||
|
variants: variants
|
||||||
|
.filter((variant) => variant.kind === "video_mp4")
|
||||||
|
.map((variant) => ({
|
||||||
|
kind: "video_mp4",
|
||||||
|
size: variant.size,
|
||||||
|
key: variant.key,
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (picked?.kind === "video_mp4") {
|
||||||
|
const url = await loadSignedUrl(assetId, "video_mp4_720");
|
||||||
|
return { url, variant: { kind: "video_mp4", size: 720 } };
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
const url = await loadSignedUrl(assetId, "original");
|
// fall through to original
|
||||||
return { url, variant: { kind: "original" } };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const url = await loadSignedUrl(assetId, "original");
|
||||||
|
return { url, variant: { kind: "original" } };
|
||||||
}
|
}
|
||||||
|
|
||||||
async function openViewer(asset: Asset) {
|
async function openViewer(asset: Asset) {
|
||||||
|
|||||||
@@ -9,14 +9,14 @@ type PlaybackInput = {
|
|||||||
variants: Variant[];
|
variants: Variant[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export function pickVideoPlaybackVariant(input: PlaybackInput):
|
export function pickVideoPlaybackVariant(
|
||||||
| { kind: "video_mp4"; size: number }
|
input: PlaybackInput,
|
||||||
| { kind: "original" } {
|
): { kind: "video_mp4"; size: number } | null {
|
||||||
const mp4Variant = input.variants.find(
|
const mp4Variant = input.variants.find(
|
||||||
(variant) => variant.kind === "video_mp4" && variant.size === 720,
|
(variant) => variant.kind === "video_mp4" && variant.size === 720,
|
||||||
);
|
);
|
||||||
if (mp4Variant) {
|
if (mp4Variant) {
|
||||||
return { kind: "video_mp4", size: mp4Variant.size };
|
return { kind: "video_mp4", size: mp4Variant.size };
|
||||||
}
|
}
|
||||||
return { kind: "original" };
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ test("prefer mp4 derived over original", () => {
|
|||||||
expect(picked).toEqual({ kind: "video_mp4", size: 720 });
|
expect(picked).toEqual({ kind: "video_mp4", size: 720 });
|
||||||
});
|
});
|
||||||
|
|
||||||
test("falls back to original when no derived", () => {
|
test("returns null when no mp4 variants", () => {
|
||||||
const picked = pickVideoPlaybackVariant({
|
const picked = pickVideoPlaybackVariant({
|
||||||
originalMimeType: "video/x-matroska",
|
originalMimeType: "video/x-matroska",
|
||||||
variants: [],
|
variants: [],
|
||||||
});
|
});
|
||||||
expect(picked).toEqual({ kind: "original" });
|
expect(picked).toBeNull();
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user