Startet nur nach Klick; mit Vorschaubild (intro.jpg) lädt vorab nichts vom Video. Vorschaubilder von Intro und Reels laufen über die Bildoptimierung statt im Original, Videos bevorzugen eine Web-Fassung <name>.web.mp4. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
55 lines
2.2 KiB
TypeScript
55 lines
2.2 KiB
TypeScript
import type { Media } from "@/content/site";
|
|
import { optimizedImageUrl } from "@/lib/image-url";
|
|
import { MediaFrame } from "./MediaFrame";
|
|
|
|
/** Reels sind hoch und hoechstens ein Drittel breit. */
|
|
const POSTER_WIDTH = 1080;
|
|
|
|
type Slot = { name: string | null; caption: string | null; poster: Media | null; src: string | null };
|
|
|
|
/**
|
|
* Ein Video aus dem eigenen Medienverzeichnis, im eigenen Seitenverhaeltnis
|
|
* (quer oder hoch). Es startet nie von selbst. Mit Vorschaubild laedt vorab
|
|
* nichts vom Video, ohne nur Metadaten und erstes Bild (#t=0.1). Kein
|
|
* externer Anbieter.
|
|
*/
|
|
export function VideoSlot({ slot, index, showDrafts }: { slot: Slot; index: number; showDrafts: boolean }) {
|
|
const label = slot.name ? `Video von ${slot.name}` : `Video ${index + 1}`;
|
|
// Vorschaubild ueber die Bildoptimierung statt im Original (ein Reel-PNG
|
|
// hatte 1,3 MB); mit Vorschaubild laedt vom Video vorab nichts.
|
|
const poster = slot.poster?.kind === "image" ? optimizedImageUrl(slot.poster.src, POSTER_WIDTH) : undefined;
|
|
|
|
return (
|
|
<figure>
|
|
{slot.src ? (
|
|
<video
|
|
src={poster ? slot.src : `${slot.src}#t=0.1`}
|
|
poster={poster}
|
|
controls
|
|
playsInline
|
|
preload={poster ? "none" : "metadata"}
|
|
aria-label={label}
|
|
className="mx-auto block max-h-[80vh] w-full rounded-2xl bg-ink object-contain"
|
|
>
|
|
<track kind="captions" />
|
|
</video>
|
|
) : (
|
|
<div className="relative aspect-[9/16] overflow-hidden rounded-2xl">
|
|
<MediaFrame
|
|
media={slot.poster ?? { kind: "placeholder", label: `Video ${index + 1} folgt`, tone: "studio" }}
|
|
aspect="h-full w-full"
|
|
sizes="(min-width: 640px) 33vw, 100vw"
|
|
showLabel={showDrafts}
|
|
/>
|
|
</div>
|
|
)}
|
|
{(slot.name || slot.caption || (showDrafts && !slot.src)) && (
|
|
<figcaption className="mt-4">
|
|
{slot.name ? <span className="block font-semibold">{slot.name}</span> : showDrafts && <span className="draft-flag">Name und Freigabe folgen</span>}
|
|
{slot.caption && <span className="mt-1 block opacity-80">{slot.caption}</span>}
|
|
</figcaption>
|
|
)}
|
|
</figure>
|
|
);
|
|
}
|