Limeplay - Open Source Video Player UI ComponentsLimeplay

use-timeline

Hook for managing timeline state, seeking, and buffered ranges

Installation

Install the hook

npx shadcn add @limeplay/use-timeline

Add Event & Action Bridge

Import the useTimelineStates hook in your existing PlayerHooks component.

components/limeplay/player-hooks.tsx
import React from "react"

import { useShakaPlayer } from "@/hooks/limeplay/use-shaka-player"
import { useTimelineStates } from "@/hooks/limeplay/use-timeline"

export const PlayerHooks = React.memo(() => {
  useShakaPlayer()
  useTimelineStates() 

  return null
})

Add the Store States

lib/create-media-store.ts
import { createPlayerStore, PlayerStore } from "@/hooks/limeplay/use-player"
import {
  createTimelineStore,
  TimelineStore,
} from "@/hooks/limeplay/use-timeline"


export type TypeMediaStore = PlayerStore & TimelineStore & {} 

export function createMediaStore(initProps?: Partial<CreateMediaStoreProps>) {
  const mediaStore = create<TypeMediaStore>()((...etc) => ({
    ...createPlayerStore(...etc),
    ...createTimelineStore(...etc),
    ...initProps,
  }))
  return mediaStore
}

Example Usage

Use the useTimeline() hook to implement seeking functionality.

components/player/timeline-slider.tsx
import { useTimeline } from "@/hooks/limeplay/use-timeline"
import { useMediaStore } from "@/components/limeplay/media-provider"

export function TimelineSlider() {
  const duration = useMediaStore((state) => state.duration)
  const currentTime = useMediaStore((state) => state.currentTime)
  const { seek, getTimeFromEvent } = useTimeline()

  return (
    <div
      onPointerDown={(e) => {
        const time = getTimeFromEvent(e)
        seek(time)
      }}
    >
      <div style={{ width: `${(currentTime / duration) * 100}%` }} />
    </div>
  )
}

Understanding

The use-timeline hook provides comprehensive timeline management following the Event & Action Bridge pattern:

  • Event Bridge: useTimelineStates() polls media state (default 500ms) and listens to durationchange, progress, and Shaka Player events to update currentTime, duration, progress, and buffered ranges
  • Action Bridge: useTimeline() provides seek(), setHoveringTime(), and getTimeFromEvent() functions for timeline interactions

Live Stream Support

The hook automatically handles live streams:

  • Uses Shaka Player's seekRange() for proper DVR seeking
  • Calculates live latency
  • Adjusts progress calculation for sliding window streams
  • Provides isLive and liveLatency state

Buffered Ranges

The hook provides processBufferedRanges() function that supports three variants:

  • default - Shows all buffered ranges as-is
  • combined - Combines all ranges into a single range
  • from-zero - Shows ranges starting from 0

API Reference

useTimelineStates

Sets up polling and event listeners for timeline state updates.

Parameters

PropertyTypeDefaultDescription
updateDurationnumber500Interval in milliseconds to update timeline state

useTimeline()

Returns control functions for timeline interactions.

Returns

PropertyTypeDescription
seek(time: number) => voidSeeks to the specified time (handles live streams)
setHoveringTime(time: number) => voidSets the hover time for timeline preview
setIsHovering(isHovering: boolean) => voidSets the hovering state
getTimeFromEvent(event: React.PointerEvent) => numberCalculates time from pointer event position
processBufferedRanges(ranges: BufferedRange[], variant?: string) => ArrayProcesses buffered ranges for display

Store State

The timeline store provides the following state accessed via useMediaStore:

PropertyTypeDescription
durationnumberTotal media duration in seconds
currentTimenumberCurrent playback time in seconds
progressnumberPlayback progress (0-1)
hoveringTimenumberTime at cursor position on timeline
isHoveringbooleanWhether the user is hovering over the timeline
bufferedshaka.extern.BufferedRange[]Array of buffered time ranges
liveLatencynumber | nullLive stream latency in seconds (null for VOD)
isLivebooleanWhether the media is a live stream