Skip to main content

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

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 />
}