Channel → live video → stream URL → image.
- 🔴 Find the current live video for a YouTube channel
- 🖼️ Capture one frame as a
Bufferor file - 🧰 Use as an SDK or CLI
- 🧪 Mockable command runner for tests
- 🚫 No AI, OCR, browser automation, or scraping UI required
npm install livestillLiveStill shells out to these tools:
brew install yt-dlp ffmpegimport { writeFile } from "node:fs/promises";
import { captureYouTubeLiveFrame, findYouTubeLiveVideo } from "livestill";
const status = await findYouTubeLiveVideo({ url: "https://www.youtube.com/@marvel/" });
if (!status.isLive) {
throw new Error("Channel is not live");
}
const frame = await captureYouTubeLiveFrame(status.video.url, { format: "jpg" });
await writeFile("frame.jpg", frame.image);# Find current live URL
livestill live @marvel
livestill live https://www.youtube.com/@marvel/ --json
# Capture a frame
livestill capture @marvel --out marvel.jpg
livestill capture https://www.youtube.com/watch?v=f17J3AXVK5w --out frame.jpgawait findYouTubeLiveVideo({ handle: "@marvel" });
await findYouTubeLiveVideo({ channelId: "UCxxxxxxxxxxxxxxxxxxxxxx" });
await findYouTubeLiveVideo({ url: "https://www.youtube.com/@marvel/" });Returns:
type YouTubeLiveStatus =
| { isLive: false }
| { isLive: true; video: { videoId: string; url: string; title?: string } };const frame = await captureYouTubeLiveFrame("https://www.youtube.com/watch?v=...", {
outputPath: "frame.jpg",
});resolveDirectStreamUrl(youtubeUrl, options?)captureFrame(streamUrl, options?)createYouTubeWatchUrl(videoId)
| Runtime | Status | Notes |
|---|---|---|
| Node server / container | ✅ | Install yt-dlp + ffmpeg |
| AWS Lambda | ✅ | Bundle binaries in a layer/container |
| Edge/browser runtimes | ❌ | No child processes/filesystem |
Direct stream URLs expire. Resolve close to capture time and keep yt-dlp
updated.
pnpm run verify
pnpm run test:integration
pnpm packMIT