clip-card HLS MP4
How previews work, on one card: the clip plays on hover, gets the film ready from its moment, and a tap opens the film there
import { playFullscreen, preload, useVideo, Video } from "@uln/hls/react";
import { useState } from "react";
import { film } from "../films";
/**
* How a preview works, on one card. A preview is not a separate feature: it
* is a `<Video>` given the film's short silent clip instead of the film.
*
* 1. Hovering or focusing the card plays the clip (`playing`). The clip
* downloads whole into memory, so it starts on its first frame and never stalls.
* 2. Once it plays, the film gets ready to open from the clip's moment
* (`preload` with `start`): its opening at that moment lands in the HTTP cache.
* 3. A tap opens the film in the phone's own player at the same moment
* (`playFullscreen` with `start`). On desktop, `fallback` opens your own player.
*/
export function App() {
const clip = useVideo();
const [active, setActive] = useState(false);
if (!film.clip) return <img src={film.poster} alt={film.title} />;
const clipStart = film.clip.start;
// Where the film is at this moment of the clip.
const filmTime = () => clipStart + clip.currentTime;
return (
<button
type="button"
className="card"
onPointerEnter={() => setActive(true)}
onPointerLeave={() => setActive(false)}
onFocus={() => setActive(true)}
onBlur={() => setActive(false)}
onClick={() => playFullscreen(film.hls, { start: filmTime(), poster: film.poster })}
>
<Video
src={film.clip.url}
poster={film.poster}
player={clip}
playing={active}
muted
loop
onPlay={() => preload(film.hls, { start: filmTime() })}
/>
<span>{film.title}</span>
</button>
);
}