Advanced

Autoplay

How autoplay works across browsers and how ytcn handles it.

Browser autoplay policies

Modern browsers restrict autoplay to prevent unwanted noise. The general rule is: autoplay with sound is blocked unless the user has interacted with the page. Autoplay with muted audio is usually allowed.

BrowserMuted autoplayUnmuted autoplay
Chrome (desktop)✅ Always🔶 After user interaction
Firefox✅ Always🔶 After user interaction
Safari (desktop)✅ Always❌ Blocked by default
iOS Safari✅ Always (inline)❌ Blocked
Android Chrome✅ Always🔶 After user interaction

ytcn's approach

ytcn uses a thumbnail-first strategy by default. The video does not autoplay — the user clicks the thumbnail to start. This avoids all browser autoplay restrictions and provides a faster perceived load time.

No flicker

Because ytcn loads a CDN thumbnail first (under 100ms), the user sees content immediately. The iframe loads behind the thumbnail. When the user clicks play, the transition is seamless — no black screen, no YouTube branding flash.

Forcing autoplay (advanced)

If you need autoplay behavior, you can use the headless hook to programmatically start playback after a user interaction elsewhere on the page:

autoplay-after-interaction.tsx
"use client"

import { useYtcnPlayer } from "@/hooks/ytcn/use-ytcn-player"
import { useEffect, useRef } from "react"

export function AutoplayPlayer({ videoId }: { videoId: string }) {
  const { containerRef, playerDivRef, state, controls } =
    useYtcnPlayer({ videoId })
  const hasAutoPlayed = useRef(false)

  // Autoplay once the player is ready
  useEffect(() => {
    if (state.phase === "ready" && !hasAutoPlayed.current) {
      hasAutoPlayed.current = true
      controls.togglePlay()
    }
  }, [state.phase, controls])

  return (
    <div ref={containerRef} className="relative aspect-video">
      <div ref={playerDivRef} className="absolute inset-0" />
    </div>
  )
}

Muted autoplay

For reliable autoplay without user interaction, you must mute the video. Call controls.toggleMute() before controls.togglePlay().