Ambient Glow Video
A video with YouTube-style ambient mode: every frame is also drawn onto a tiny 64x36 canvas sitting behind the player, blurred far past recognition, so the surface glows with whatever colors are on screen right now. drawImage runs in the normal paint cycle — no WebGL, no compositing tricks, near-zero cost.
CardReactCanvas 2DTailwind CSS
CSSTailwind
Manual
Create a file and paste the following code into it.
ambient-glow-video.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
"use client";
import { useEffect, useRef } from "react";
import { cn } from "@/lib/cn";
/* ------------------------------------------------------------------ */
/* AmbientGlowVideo */
/* ------------------------------------------------------------------ */
interface AmbientGlowVideoProps {
src: string;
poster?: string;
/** Blur radius of the glow canvas in px [Optional, default: 60] */
blurAmount?: number;
/** Glow opacity 0-1 [Optional, default: 0.85] */
intensity?: number;
autoPlay?: boolean;
muted?: boolean;
/** Show native controls [Optional, default: true] */
controls?: boolean;
className?: string;
}
/* Tiny canvas — the blur erases any pixel detail anyway, and a 64x36 draw
per frame costs nearly nothing. */
const CANVAS_W = 64;
const CANVAS_H = 36;
/**
* A video with YouTube-style ambient mode: every frame is also drawn onto a
* tiny canvas sitting behind the player, blurred far past recognition, so
* the page glows with whatever colors are on screen right now. drawImage
* runs in the normal paint cycle — no WebGL, no compositing tricks.
* @param {string} src - Video source [Required]
* @param {number} blurAmount - Glow blur radius [Optional, default: 60]
*/
export function AmbientGlowVideo({
src,
poster,
blurAmount = 60,
intensity = 0.85,
autoPlay = false,
muted = false,
controls = true,
className,
}: AmbientGlowVideoProps) {
const videoRef = useRef<HTMLVideoElement | null>(null);
const canvasRef = useRef<HTMLCanvasElement | null>(null);
const rafRef = useRef(0);
useEffect(() => {
const video = videoRef.current;
const ctx = canvasRef.current?.getContext("2d");
if (!video || !ctx) return;
const draw = () => {
if (!video.paused || video.readyState >= 2) {
try {
ctx.drawImage(video, 0, 0, CANVAS_W, CANVAS_H);
} catch {
/* cross-origin canvas taint — keep playing without the glow */
}
}
rafRef.current = requestAnimationFrame(draw);
};
rafRef.current = requestAnimationFrame(draw);
return () => cancelAnimationFrame(rafRef.current);
}, []);
return (
<div className={cn("relative w-full", className)}>
<canvas
ref={canvasRef}
width={CANVAS_W}
height={CANVAS_H}
aria-hidden
className="pointer-events-none absolute inset-0 h-full w-full rounded-xl"
style={{
filter: `blur(${blurAmount}px)`,
opacity: intensity,
transform: "scale(1.08)",
}}
/>
<video
ref={videoRef}
src={src}
poster={poster}
controls={controls}
playsInline
preload="metadata"
autoPlay={autoPlay}
muted={muted}
loop
className="relative z-[1] w-full rounded-xl"
/>
</div>
);
}
Update the import paths to match your project setup.
Similar components
Install via CLI
Resource details
PublishedJuly 17, 2026
CategoryCard
ReactCanvas 2DTailwind CSS
Install via CLI
Resource details
PublishedJuly 17, 2026
CategoryCard
ReactCanvas 2DTailwind CSS