+
diff --git a/src/frontend/src/components/YouTubeCard.astro b/src/frontend/src/components/YouTubeCard.astro
index 66aef35c6..96222f89a 100644
--- a/src/frontend/src/components/YouTubeCard.astro
+++ b/src/frontend/src/components/YouTubeCard.astro
@@ -45,34 +45,44 @@ const { href, title, description, tags } = Astro.props;
diff --git a/src/frontend/src/components/YouTubeEmbed.astro b/src/frontend/src/components/YouTubeEmbed.astro
index 1f13cefc8..381edffa4 100644
--- a/src/frontend/src/components/YouTubeEmbed.astro
+++ b/src/frontend/src/components/YouTubeEmbed.astro
@@ -1,9 +1,11 @@
---
export interface Props {
/** YouTube video or live stream ID (the ?v= value) */
- videoId: string;
- /** Accessible title for the iframe */
- title?: string;
+ videoId?: string;
+ /** YouTube channel ID for the channel live-stream embed */
+ channelId?: string;
+ /** Accessible label for the iframe */
+ title?: string | null;
/** Aspect ratio — default 16/9 */
aspectRatio?: string;
/** Autoplay the stream (muted, as browsers require) */
@@ -14,33 +16,45 @@ export interface Props {
const {
videoId,
+ channelId,
title = 'YouTube video player',
aspectRatio = '16 / 9',
autoplay = false,
maxWidth = '100%',
} = Astro.props;
+if (!videoId && !channelId) {
+ throw new Error('YouTubeEmbed requires either a `videoId` or `channelId` prop.');
+}
+
const params = new URLSearchParams({
rel: '0',
modestbranding: '1',
playsinline: '1',
});
+if (channelId) {
+ params.set('channel', channelId);
+}
if (autoplay) {
params.set('autoplay', '1');
params.set('mute', '1');
}
-const src = `https://www.youtube-nocookie.com/embed/${videoId}?${params.toString()}`;
+const embedPath = channelId ? 'live_stream' : encodeURIComponent(videoId!);
+const src = `https://www.youtube-nocookie.com/embed/${embedPath}?${params.toString()}`;
---
-
+
+ data-stream-provider="youtube">