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.
| Browser | Muted autoplay | Unmuted 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().