To add video or audio to a Lovable project, use HTML5 video and audio tags for self-hosted media files in the /public folder, or embed YouTube and Vimeo with responsive iframe containers. Browser autoplay policies block autoplay with sound — add the muted attribute alongside autoplay for videos that need to play automatically. Wrap video iframes in an aspect-ratio container using Tailwind's aspect-video class for responsive sizing.
Why video and audio elements may not work correctly in Lovable
Adding media to a Lovable project is straightforward, but several browser behaviors can make videos and audio appear broken even when the code is correct. The most common issue is autoplay policy enforcement. Modern browsers (Chrome, Safari, Firefox) block autoplaying media that has sound. If you add autoplay to a video tag without also adding the muted attribute, the browser silently refuses to play it — no error appears, the video just sits frozen. For self-hosted video and audio files, the file must be in the /public folder with the correct path. Lovable's Vite build serves static files from /public at the root URL, so a file at /public/videos/intro.mp4 is accessed as /videos/intro.mp4 in your code. Getting this path wrong results in a broken media player with no content. Embedding YouTube or Vimeo videos requires an iframe rather than a video tag. The main issue with iframes is responsive sizing — without proper CSS, the embedded video either has a fixed pixel size that breaks on mobile or collapses to zero height. Tailwind's aspect-video class combined with a width-full container solves this reliably.
- Autoplay blocked by browser: video has autoplay but is missing the muted attribute
- Wrong file path: media file is not in /public or the src path does not match the actual file location
- Missing controls attribute: video/audio element renders but has no play button visible to the user
- Non-responsive iframe: YouTube/Vimeo embed has fixed dimensions that break on mobile screens
- CORS restrictions: media hosted on a different domain blocks loading due to cross-origin policy
Error messages you might see
DOMException: play() failed because the user didn't interact with the document firstThe browser blocked autoplay because the video has sound. Add the muted attribute to the video tag alongside autoplay. Browsers allow muted autoplay but block autoplay with audio until the user interacts with the page.
GET /videos/intro.mp4 404 (Not Found)The video file is not at the expected path. Place your media file in the /public folder and use a root-relative path starting with / in the src attribute. For example, /public/videos/intro.mp4 is accessed as /videos/intro.mp4.
Refused to display 'https://www.youtube.com/watch?v=...' in a frame because it set 'X-Frame-Options' to 'sameorigin'You are trying to embed a regular YouTube URL in an iframe. YouTube watch URLs block iframe embedding. Use the embed URL format instead: https://www.youtube.com/embed/VIDEO_ID.
Before you start
- A Lovable project open in the editor
- Your video or audio file (for self-hosted) or the YouTube/Vimeo video URL (for embeds)
- For self-hosted files: access to the /public folder via GitHub or Dev Mode to upload media files
How to fix it
Add a self-hosted video with HTML5 video tag
The HTML5 video element is the standard way to play video files hosted in your project
Add a self-hosted video with HTML5 video tag
The HTML5 video element is the standard way to play video files hosted in your project
First, upload your video file to the /public/videos/ folder via GitHub or Dev Mode. Then add a video element in your component with the src pointing to the file using a root-relative path. Always include the controls attribute so users can play, pause, and seek. If you want the video to autoplay, you must also add the muted attribute — browsers block autoplay with sound.
<!-- Broken: autoplay without muted, missing controls --><video autoplay src="videos/intro.mp4"> Your browser does not support the video tag.</video>{/* Video won't autoplay and user can't manually play either */}<!-- Working: muted autoplay with controls and responsive sizing --><video autoPlay muted controls loop playsInline className="w-full max-w-2xl rounded-lg" src="/videos/intro.mp4"> Your browser does not support the video tag.</video>{/* Note: autoPlay is camelCase in JSX, playsInline prevents fullscreen on iOS */}Expected result: The video plays automatically (muted) when the page loads and shows playback controls. The user can unmute manually using the controls.
Embed a YouTube or Vimeo video with a responsive iframe
Third-party video platforms require iframe embeds with the correct embed URL format
Embed a YouTube or Vimeo video with a responsive iframe
Third-party video platforms require iframe embeds with the correct embed URL format
For YouTube, use the embed URL format: https://www.youtube.com/embed/VIDEO_ID (not the regular watch URL). For Vimeo, use https://player.vimeo.com/video/VIDEO_ID. Wrap the iframe in a container with Tailwind's aspect-video class to maintain the 16:9 aspect ratio and make it responsive. Add allow attributes for fullscreen and autoplay if desired.
<!-- Broken: using watch URL and fixed pixel dimensions --><iframe width="560" height="315" src="https://www.youtube.com/watch?v=dQw4w9WgXcQ"></iframe>{/* X-Frame-Options error and non-responsive on mobile */}<!-- Working: embed URL with responsive container --><div className="w-full max-w-3xl aspect-video"> <iframe className="w-full h-full rounded-lg" src="https://www.youtube.com/embed/dQw4w9WgXcQ" title="Video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen /></div>{/* Responsive 16:9 container that works on all screen sizes */}Expected result: The YouTube video loads and plays inside a responsive container that maintains 16:9 aspect ratio on desktop and mobile.
Add an audio player with HTML5 audio tag
The audio element provides a built-in player UI for music, podcasts, or sound effects
Add an audio player with HTML5 audio tag
The audio element provides a built-in player UI for music, podcasts, or sound effects
Add an audio element with the controls attribute and point the src to your audio file in /public. The browser renders a native audio player with play/pause, timeline, and volume controls. For multiple audio format support, use source elements inside the audio tag with different file formats (MP3, OGG, WAV) so the browser picks the one it supports.
<!-- Broken: audio file not in /public, no controls --><audio src="podcast.mp3" autoplay />{/* No visible player, autoplay blocked, file 404 */}<!-- Working: file in /public, controls visible, fallback formats --><audio controls className="w-full max-w-md"> <source src="/audio/podcast.mp3" type="audio/mpeg" /> <source src="/audio/podcast.ogg" type="audio/ogg" /> Your browser does not support the audio element.</audio>{/* Native player UI with play/pause, seek, and volume */}Expected result: A visible audio player appears on the page. The user can click play to start listening, seek through the timeline, and adjust volume.
Create a reusable video embed component
If your project uses multiple video embeds, a reusable component keeps the code DRY and consistent
Create a reusable video embed component
If your project uses multiple video embeds, a reusable component keeps the code DRY and consistent
Create a component that accepts a video URL and optional props for autoplay and aspect ratio. This component handles the responsive container, correct iframe attributes, and URL format validation. Use it across multiple pages without repeating the iframe boilerplate. If you need advanced video features like custom controls, analytics tracking, or adaptive bitrate streaming, RapidDev's engineers can implement these patterns for you.
// Repeating iframe code on every page<iframe src="https://www.youtube.com/embed/abc" width="560" height="315" /><iframe src="https://www.youtube.com/embed/def" width="560" height="315" />{/* Inconsistent sizing, no responsive behavior */}// Using the reusable VideoEmbed componentimport VideoEmbed from "@/components/VideoEmbed";<VideoEmbed url="https://www.youtube.com/embed/abc" title="Tutorial 1" /><VideoEmbed url="https://www.youtube.com/embed/def" title="Tutorial 2" />{/* Consistent responsive behavior across all embeds */}Expected result: All video embeds on the site have consistent responsive sizing and proper iframe attributes. Adding new videos requires just one line of code.
Complete code example
1import { cn } from "@/lib/utils";23interface VideoEmbedProps {4 url: string;5 title: string;6 className?: string;7 autoplay?: boolean;8}910// Reusable responsive video embed component11// Works with YouTube, Vimeo, and any iframe-compatible video URL12const VideoEmbed = ({ url, title, className, autoplay = false }: VideoEmbedProps) => {13 // Append autoplay parameter if requested14 const embedUrl = autoplay && !url.includes("autoplay")15 ? `${url}${url.includes("?") ? "&" : "?"}autoplay=1&mute=1`16 : url;1718 return (19 <div className={cn("w-full aspect-video", className)}>20 <iframe21 className="w-full h-full rounded-lg"22 src={embedUrl}23 title={title}24 allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"25 allowFullScreen26 />27 </div>28 );29};3031// Example page using the component32const VideoPage = () => {33 return (34 <div className="container mx-auto py-8 space-y-8">35 <h1 className="text-3xl font-bold">Video Gallery</h1>3637 {/* YouTube embed */}38 <VideoEmbed39 url="https://www.youtube.com/embed/dQw4w9WgXcQ"40 title="Product demo"41 className="max-w-3xl"42 />4344 {/* Self-hosted video with native player */}45 <video46 controls47 playsInline48 className="w-full max-w-3xl rounded-lg"49 src="/videos/tutorial.mp4"50 >51 Your browser does not support the video tag.52 </video>53 </div>54 );55};5657export default VideoEmbed;Best practices to prevent this
- Always add muted alongside autoplay — browsers block autoplay with sound, but muted autoplay is allowed on all platforms
- Use the aspect-video Tailwind class on the iframe container to maintain 16:9 ratio responsively
- Add playsInline to video tags so mobile Safari does not force fullscreen playback
- Use YouTube/Vimeo embed URLs (youtube.com/embed/ID, player.vimeo.com/video/ID) not regular watch URLs in iframes
- Place self-hosted media files in /public/videos/ or /public/audio/ and reference with root-relative paths starting with /
- Always include the controls attribute on video and audio elements so users can play, pause, and seek
- Add a title attribute to iframes for accessibility — screen readers use it to describe the embedded content
- Compress video files before uploading — large files slow page load; consider using a video hosting service for files over 10MB
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I need to add video and audio to my Lovable (lovable.dev) React + TypeScript project. I want to: 1. Embed a YouTube video responsively: [paste YouTube URL] 2. Add a self-hosted video file from my /public folder 3. Add an audio player for a podcast MP3 Please provide: 1. A responsive YouTube embed component using Tailwind's aspect-video 2. An HTML5 video element with autoplay (muted), controls, and playsInline 3. An HTML5 audio element with controls and fallback format support 4. All code must be valid React JSX (camelCase attributes like autoPlay, playsInline, allowFullScreen)
Add a responsive YouTube video embed to @src/pages/Home.tsx. Use the embed URL https://www.youtube.com/embed/[VIDEO_ID] inside an iframe wrapped in a div with className 'w-full max-w-3xl aspect-video'. Include allow attributes for autoplay and fullscreen. Also add an HTML5 audio player below the video for the file at /audio/intro.mp3 with visible controls. Make sure both elements are responsive on mobile.
Frequently asked questions
Why is my video not autoplaying in Lovable?
Modern browsers block autoplay for videos with sound. Add both the autoPlay and muted attributes (camelCase in JSX) to your video tag. The browser allows muted autoplay on all platforms. Users can then unmute manually using the video controls.
How do I embed a YouTube video in a Lovable project?
Use an iframe with the embed URL format: https://www.youtube.com/embed/VIDEO_ID (not the regular watch URL). Wrap the iframe in a div with Tailwind's aspect-video class for responsive 16:9 sizing. Add allowFullScreen and appropriate allow attributes.
Where do I put video files in a Lovable project?
Place video and audio files in the /public folder, ideally in a subfolder like /public/videos/. Upload them via GitHub or Dev Mode. Reference them in your code with root-relative paths: /videos/filename.mp4. Vite serves /public contents at the site root.
How do I make an embedded video responsive on mobile?
Wrap the iframe in a div with className="w-full aspect-video" and set the iframe to className="w-full h-full". Tailwind's aspect-video class maintains a 16:9 aspect ratio while the w-full class makes the container fill its parent width on any screen size.
Can I use Vimeo videos in Lovable?
Yes. Use the Vimeo embed URL format: https://player.vimeo.com/video/VIDEO_ID. The iframe setup is identical to YouTube embeds. Wrap in an aspect-video container with the same allow attributes for fullscreen and autoplay.
Why does my video show a CORS error?
This happens when loading a video file from a different domain that does not allow cross-origin requests. For self-hosted files, keep them in your /public folder. For external URLs, the server must include proper CORS headers. Using YouTube or Vimeo embed URLs avoids this issue entirely.
What if I need advanced video features in my Lovable project?
If you need custom video controls, progress tracking, adaptive bitrate streaming, or DRM protection, these require additional libraries and configuration. RapidDev's engineers have implemented advanced media players across 600+ Lovable projects and can set this up for you.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your issue.
Book a free consultation