Hook

useYtcnPlayer

Core hook. Returns player refs, reactive state, and imperative controls.

Signature

signature
const { containerRef, playerDivRef, state, controls } =
  useYtcnPlayer(options)

Options

videoId*
string

YouTube video ID to load.

startAt0
number

Initial playback position in seconds.

onEnd
() => void

Called when the video finishes playing.

onTimeUpdate
(current: number, duration: number) => void

Called every 250ms during playback with current time and total duration.

keyboardShortcutstrue
boolean

Enable built-in keyboard shortcut handling.

Returns — State

The state object is reactive — it re-renders your component when any field changes.

phase
"thumbnail" | "loading" | "ready"

Current player lifecycle phase. Thumbnail is shown first, then loading while iframe initializes, then ready when playback begins.

isPlaying
boolean

Whether the video is currently playing.

isMuted
boolean

Whether the video is currently muted.

volume
number

Current volume level from 0 to 100.

currentTime
number

Current playback position in seconds. Polled every 250ms.

duration
number

Total video duration in seconds.

loadedFraction
number

Buffer progress from 0 to 1.

isLoading
boolean

True while the player is initializing.

isFullscreen
boolean

True when in fullscreen mode.

playbackRate
0.75 | 1 | 1.5 | 2

Currently active playback speed.

Returns — Controls

togglePlay()
() => void

Play or pause the video.

seekTo(seconds)
(s: number) => void

Jump to an absolute position in seconds.

seekRelative(delta)
(d: number) => void

Seek ±N seconds from current position.

setVolume(0–100)
(v: number) => void

Set volume level. Also unmutes if muted.

toggleMute()
() => void

Toggle mute state.

setSpeed(speed)
(s: PlaybackSpeed) => void

Set playback rate to 0.75, 1, 1.5, or 2.

toggleFullscreen()
() => void

Enter or exit fullscreen mode.

Stale closure warning

YouTube API callbacks fire outside React

YouTube API callbacks fire outside React's render cycle. Do not read state directly inside YT callbacks — read refs instead. useYtcnPlayer handles this internally. If you extend the hook, follow the same ref-sync pattern.
stale-closure.ts
// ❌ WRONG — state.volume is stale inside YT callback
onReady: () => player.setVolume(state.volume)

// ✅ CORRECT — ref is always current
onReady: () => player.setVolume(volumeRef.current)