Create a player
createPlayer returns a Result<BlindcastPlayer, PlayerError>. The video element must be in the DOM before you call it.
import { createPlayer } from "@blindcast/player"
const videoEl = document.getElementById("video") as HTMLVideoElement
const result = createPlayer(videoEl, {
keyServerUrl: "https://keys.example.com/keys",
})
if (!result.ok) {
console.error(result.error.code, result.error.message)
return
}
const player = result.value
keyServerUrl must include the /keys path — e.g., https://your-worker.workers.dev/keys, not just the base URL. The player appends /:contentId to this path when fetching keys.
Load a manifest
player.load("https://cdn.example.com/content/my-video/manifest.m3u8")
The player fetches the manifest, reads EXT-X-KEY tags to discover the key server URL, fetches the content key, then decrypts each segment as it downloads.
Events
Subscribe to events with player.on(). It returns an unsubscribe function.
const unsub = player.on("ready", ({ levels }) => {
console.log(`Ready — ${levels} quality levels`)
})
player.on("playing", () => console.log("Playing"))
player.on("paused", () => console.log("Paused"))
player.on("buffering", () => console.log("Buffering..."))
player.on("ended", () => console.log("Ended"))
player.on("keyLoaded", ({ contentId, epoch }) => {
console.log(`Key loaded for ${contentId}, epoch ${epoch ?? "none"}`)
})
player.on("qualitySwitch", ({ fromLevel, toLevel }) => {
console.log(`Quality: ${fromLevel} → ${toLevel}`)
})
player.on("error", (err) => {
console.error(`[${err.code}] ${err.message}`)
})
player.on("destroyed", () => {
console.log("Player destroyed")
})
// Remove a specific listener
unsub()
Metrics
Call getMetrics() at any time for a snapshot of cumulative stats since load().
const m = player.getMetrics()
console.log(`TTFF: ${m.timeToFirstFrame}ms`)
console.log(`Decrypt avg: ${m.avgDecryptTime}ms`)
console.log(`Fragments loaded: ${m.fragmentsLoaded}`)
console.log(`Stalls: ${m.stallCount}`)
Useful for dashboards, debugging, and monitoring. See Monitoring for production recommendations.
Destroy
Always call destroy() when the component unmounts or the user navigates away.
player.destroy()
// Stops playback, detaches hls.js, clears the key cache, emits "destroyed"
React example
import { useEffect, useRef } from "react"
import { createPlayer, isPlayerSupported } from "@blindcast/player"
function VideoPlayer({ manifestUrl }: { manifestUrl: string }) {
const videoRef = useRef<HTMLVideoElement>(null)
useEffect(() => {
if (!videoRef.current || !isPlayerSupported()) return
const result = createPlayer(videoRef.current, {
keyServerUrl: "https://keys.example.com/keys",
})
if (!result.ok) return
const player = result.value
player.load(manifestUrl)
return () => player.destroy()
}, [manifestUrl])
return <video ref={videoRef} controls />
}