Skip to main content
RapidDev - Software Development Agency
lovable-issues

Adding Video and Audio Elements in Lovable Projects

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.

Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner9 min read~5 minAll Lovable versions (HTML5 video/audio supported in all modern browsers)March 2026RapidDev Engineering Team
TL;DR

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 first

The 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

1

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.

Before
typescript
<!-- 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 */}
After
typescript
<!-- 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.

2

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.

Before
typescript
<!-- 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 */}
After
typescript
<!-- 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.

3

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.

Before
typescript
<!-- Broken: audio file not in /public, no controls -->
<audio src="podcast.mp3" autoplay />
{/* No visible player, autoplay blocked, file 404 */}
After
typescript
<!-- 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.

4

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.

Before
typescript
// 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 */}
After
typescript
// Using the reusable VideoEmbed component
import 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

src/components/VideoEmbed.tsx
1import { cn } from "@/lib/utils";
2
3interface VideoEmbedProps {
4 url: string;
5 title: string;
6 className?: string;
7 autoplay?: boolean;
8}
9
10// Reusable responsive video embed component
11// Works with YouTube, Vimeo, and any iframe-compatible video URL
12const VideoEmbed = ({ url, title, className, autoplay = false }: VideoEmbedProps) => {
13 // Append autoplay parameter if requested
14 const embedUrl = autoplay && !url.includes("autoplay")
15 ? `${url}${url.includes("?") ? "&" : "?"}autoplay=1&mute=1`
16 : url;
17
18 return (
19 <div className={cn("w-full aspect-video", className)}>
20 <iframe
21 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 allowFullScreen
26 />
27 </div>
28 );
29};
30
31// Example page using the component
32const VideoPage = () => {
33 return (
34 <div className="container mx-auto py-8 space-y-8">
35 <h1 className="text-3xl font-bold">Video Gallery</h1>
36
37 {/* YouTube embed */}
38 <VideoEmbed
39 url="https://www.youtube.com/embed/dQw4w9WgXcQ"
40 title="Product demo"
41 className="max-w-3xl"
42 />
43
44 {/* Self-hosted video with native player */}
45 <video
46 controls
47 playsInline
48 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};
56
57export 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.

ChatGPT Prompt

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)

Lovable Prompt

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.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your issue.

Book a free consultation

Need help with your Lovable project?

Our experts have built 600+ apps and can solve your issue fast. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.