diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index 126ed14..fe7f024 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -26,12 +26,14 @@ const { title, description, keywords, openGraph, viewTransition } = Astro.props; {title} {openGraph && ( <> - - + + {description && } + - + )} + {keywords && } diff --git a/src/layouts/website/WebsiteLayout.astro b/src/layouts/website/WebsiteLayout.astro index c14920f..187d002 100644 --- a/src/layouts/website/WebsiteLayout.astro +++ b/src/layouts/website/WebsiteLayout.astro @@ -14,6 +14,7 @@ const { title, description, footer = true } = Astro.props; --- + {Astro.slots.has('head') && }
diff --git a/src/pages/video/[name].astro b/src/pages/video/[name].astro index 7c82767..f6f3992 100644 --- a/src/pages/video/[name].astro +++ b/src/pages/video/[name].astro @@ -11,19 +11,30 @@ if (!video) return new Response(null, { status: 404 }); const metadata = await getVideoMetadata(video); if (!metadata) return new Response(null, { status: 404 }); -const { title, description } = metadata; +const { title, description, width, height, duration } = metadata; const basePath = import.meta.env.BASE_URL.replace(/\/$/, ''); -const streamUrl = `${basePath}/video/${encodeURIComponent(video.name)}/stream`; +const streamPath = `${basePath}/video/${encodeURIComponent(video.name)}/stream`; +const streamUrl = new URL(streamPath, Astro.url); --- - + + + + + {streamUrl.href.startsWith('https://') && } + + {width && } + {height && } + {duration && } + +

Video

{title}

- + {description && (

{description}

diff --git a/src/util/video.ts b/src/util/video.ts index 18ee076..faa2e61 100644 --- a/src/util/video.ts +++ b/src/util/video.ts @@ -26,13 +26,15 @@ export interface VideoRange { export interface VideoMetadata { title: string; description: string | null; + width: number | null; + height: number | null; + duration: number | null; } interface VideoMetadataCacheEntry { modifiedAtMs: number; size: number; - title: string; - description: string | null; + metadata: VideoMetadata; } const videoMetadataCache = new Map(); @@ -83,22 +85,28 @@ export async function getVideoMetadata(video: ResolvedVideo): Promise track.video); + const duration = parsed.format.containerDuration ?? parsed.format.duration; + metadata = { title: parsed.common.title?.trim() || video.name, description: parsed.common.longDescription?.trim() || parsed.common.description?.map((value) => value.trim()).find(Boolean) || - null + null, + width: videoTrack?.video?.displayWidth ?? videoTrack?.video?.pixelWidth ?? null, + height: videoTrack?.video?.displayHeight ?? videoTrack?.video?.pixelHeight ?? null, + duration: duration ? Math.round(duration) : null }; } catch { // couldn't read metadata @@ -108,7 +116,7 @@ export async function getVideoMetadata(video: ResolvedVideo): Promise