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 && }
+
+
-
+
{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