Headlessplayback

website·Indexed 29 days ago

https://willnguyen1312.github.io/headlessplayback/

A library for powering playback experiences with a headless approach, allowing developers to bring their own UI. It features a core API including createPlayback and a plugin system for extending functionality with modules like hls, dash, zoomable, rotatable, and hijack. Official adapters are provided for React, Vue, Svelte, Solid, Preact, Qwik, and Angular.

Tokens
5.3K
Snippets
38
Records
38
Agent score
74%

What's inside Headlessplayback

  1. Initialize and control playback with createPlayback

    The createPlayback function creates a playback controller instance. It provides methods to activate the playback, manage its state, execute control actions, and handle cleanup. It also supports extending functionality via plugins.
    const {
      activate,
      getState,
      cleanup,
      onCleanup,
      playbackActions,
      subscribe,
      use,
    } = createPlayback({
      id: "playback",
    })
    
    // Start playback when the DOM element is available
    activate()
    
    // Get current playback state
    const currentState = getState()
    
    // Control playback (e.g., mute audio)
    playbackActions.setMuted(true)
    
    // Listen for state changes
    const unsubscribe = subscribe(({ state, updatedProperties }) => {
      console.log("State updated:", state)
    })
    
    // Register a cleanup callback
    onCleanup(() => {
      console.log("cleanup is called")
    })
    
    // Destroy the playback instance
    cleanup()
    
    // Extend functionality with a plugin
    use(plugin)
  2. Integrate and use the zoomable playback plugin

    To add zoom functionality to a playback instance, register the zoomablePlaybackPlugin with createPlayback and then call createZoomablePlayback providing the container element where the playback is rendered.
    import { createPlayback } from "@headlessplayback/core"
    import { zoomablePlaybackPlugin } from "@headlessplayback/zoomable-plugin"
    
    // Register the plugin
    createPlayback.use(zoomablePlaybackPlugin)
    
    const { activate, playbackActions } = createPlayback({
      id: "playback",
    })
    
    activate()
    
    // Initialize the zoomable playback
    playbackActions.createZoomablePlayback({
      container: document.getElementById('playback-container'), // Reference to the playback's container element
    })
  3. Install Headlessplayback core

    Headlessplayback is a framework-agnostic playback library written in pure TypeScript with no dependencies. Install the core package using your preferred package manager.
    # Using pnpm
    pnpm add @headlessplayback/core
    
    # Using npm
    npm install @headlessplayback/core
    
    # Using yarn
    yarn add @headlessplayback/core
  4. Integrate and use the DASH playback plugin

    To enable DASH playback support in @headlessplayback/core, import the dashPlaybackPlugin and register it using createPlayback.use(). Once activated, you can load a DASH stream using the loadDashSource action.
    import { createPlayback } from "@headlessplayback/core"
    import { dashPlaybackPlugin } from "@headlessplayback/dash-plugin"
    
    // Register the plugin
    createPlayback.use(dashPlaybackPlugin)
    
    const { activate, playbackActions } = createPlayback({
      id: "playback",
    })
    
    activate()
    
    // Load a DASH source
    playbackActions.loadDashSource({
      source: "dash-source",
    })
  5. Install and initialize the rotatable plugin for headlessplayback

    To enable rotation functionality in a headless playback instance, import the rotatablePlugin and register it using createPlayback.use(). After activating the playback, use the createRotatablePlayback action to link the playback to a specific container element.
    import { createPlayback } from "@headlessplayback/core"
    import { rotatablePlugin } from "@headlessplayback/rotatable-plugin"
    
    // Register the plugin
    createPlayback.use(rotatablePlugin)
    
    const { activate, playbackActions } = createPlayback({
      id: "playback",
    })
    
    activate()
    
    // Initialize the rotatable playback with a container element
    playbackActions.createRotatablePlayback({
      container: document.getElementById('your-container-id'),
    })
  6. Install and use the hijackPlaybackPlugin

    The hijackPlaybackPlugin extends the createPlayback instance from @headlessplayback/core to provide hijacking controls. Once the plugin is registered and the playback is activated, you can use the playbackActions.hijack method to trigger a hijack event with a specific duration and frequency.
    import { createPlayback } from "@headlessplayback/core"
    import { hijackPlaybackPlugin } from "@headlessplayback/hijack-plugin"
    
    // Register the plugin
    createPlayback.use(hijackPlaybackPlugin)
    
    const { activate, playbackActions } = createPlayback({
      id: "playback",
    })
    
    activate()
    
    // Trigger a hijack
    playbackActions.hijack({
      duration: 1000,
      frequency: 4,
    })
  7. Create a custom plugin for headlessplayback

    To create a plugin, implement the Plugin type which requires an install method. The install method receives the PlaybackStore and an onCleanup hook. It must return an object containing the custom actions that will be merged into the core's playbackActions.

    To ensure type safety for custom state and actions, use TypeScript module augmentation to extend the CustomPlaybackState and CustomPlaybackActions interfaces within the @headlessplayback/core module.

    import { createPlayback } from "@headlessplayback/core"
    
    // 1. Extend types via module augmentation
    declare module "@headlessplayback/core" {
      export interface CustomPlaybackState {
        customState: string
      }
      export interface CustomPlaybackActions {
        customAction: (arg: { message: string }) => void
      }
    }
    
    type Plugin<T = unknown> = {
      install: (
        arg: {
          store: any // PlaybackStore
          onCleanup: any // OnCleanupHook
        },
        ...options: T[]
      ) => any // CustomPlaybackActions
    }
    
    // 2. Implement the plugin
    export const customPlugin: Plugin<{ configKey: string }> = {
      install({ store, onCleanup }, config) {
        const customAction = (arg: { id: string; message: string }) => {
          // Access store methods
          const { setState } = store
          setState({ customState: arg.message })
    
          // Register cleanup for this instance
          onCleanup(arg.id, () => {
            console.log("Cleaning up plugin resources")
          })
        }
    
        return { customAction }
      },
    }
    
    // 3. Usage
    createPlayback.use(customPlugin, { configKey: "value" })
    const { playbackActions, getState } = createPlayback({ id: "playback" })
    
    playbackActions.customAction({ message: "Hello" })
    console.log(getState().customState)
  8. Integrate HLS playback using the hlsPlaybackPlugin

    To enable HLS (HTTP Live Streaming) support in headlessplayback, import the hlsPlaybackPlugin and register it with createPlayback.use(). Once activated, you can use the loadHlsSource action to load an HLS stream via a source URL.
    import { createPlayback } from "@headlessplayback/core"
    import { hlsPlaybackPlugin } from "@headlessplayback/hls-plugin"
    
    // Register the HLS plugin
    createPlayback.use(hlsPlaybackPlugin)
    
    const { activate, playbackActions } = createPlayback({
      id: "playback",
    })
    
    activate()
    
    // Load an HLS source
    playbackActions.loadHlsSource({
      source: "hls-source",
    })
  9. Install plugins in headlessplayback

    Plugins are independent modules used to extend the functionality of the headlessplayback core. They can be installed in two ways:

    1. Per Instance: Call the use method returned by createPlayback to apply the plugin to a specific instance.
    2. Globally: Call the use method of the createPlayback function itself to apply the plugin to all instances.
    import { createPlayback } from "@headlessplayback/core"
    import { customPlugin } from "custom-plugin"
    
    // Global installation
    createPlayback.use(customPlugin, { /* config */ })
  10. Implement playback with Angular

    Use the PlaybackService from @headlessplayback/angular. Initialize the playback in the constructor using usePlayback() and activate it in ngAfterViewInit(). Subscribe to playbackState$ to track updates.
    <!-- playback.component.html -->
    <video src="src" [id]="id" controls />
    <p>{{ playbackState.duration }}</p>
    <p>{{ playbackState.currentTime }}</p>
    // playback.component.ts
    import { AfterViewInit, Component } from "@angular/core"
    import { PlaybackService, PlaybackState } from "@headlessplayback/angular"
    
    @Component({
      selector: "playback-component",
      templateUrl: "./playback.component.html",
      providers: [PlaybackService],
    })
    export class PlaybackNormalComponent implements AfterViewInit {
      id = "playback"
      playbackState: PlaybackState
    
      constructor(private playbackService: PlaybackService) {
        this.playbackService.usePlayback({ id: this.id })
        this.playbackState = this.playbackService.playbackState
      }
    
      ngAfterViewInit() {
        this.playbackService.activate()
        this.playbackService.playbackState$.subscribe((state) => {
          this.playbackState = state
        })
      }
    }
  11. Implement playback with Vanilla JavaScript

    Use createPlayback from @headlessplayback/core to manage a video element. You must call .activate() to start the playback logic and use .subscribe() to react to state changes like currentTime and duration.
    <video src="src" controls id="video"></video>
    <p id="duration"></p>
    <p id="currentTime"></p>
    import { createPlayback } from "@headlessplayback/core"
    
    const currentTime = document.getElementById("currentTime") as HTMLParagraphElement
    const duration = document.getElementById("duration") as HTMLParagraphElement
    
    const result = createPlayback({
      id: "playback",
    })
    
    result.subscribe(({ state }) => {
      currentTime.innerText = `Current time: ${state.currentTime}`
      duration.innerText = `Duration: ${state.duration}`
    })
    
    result.activate()
  12. Hijack plugin API reference

    The hijack plugin adds several actions to playbackActions and a state property to the playback state.

    Available Actions:

    • hijack: Triggers a hijack event. Requires frequency and duration. Optionally accepts direction.
    • setDirection: Updates the playback direction.
    • setDuration: Updates the hijack duration.
    • setFrequency: Updates the hijack frequency.

    State and Types:

    • Direction: Can be either 'forward' or 'backward'.
    interface CustomPlaybackActions {
      hijack: (arg: {
        frequency: number
        duration: number
        direction?: Direction
      }) => void
      setDirection: (arg: { direction: Direction }) => void
      setDuration: (arg: { duration: number }) => void
      setFrequency: (arg: { frequency: number }) => void
    }
    
    interface CustomPlaybackState {
      direction: Direction
    }
    
    type Direction = "forward" | "backward"