Youtube Video Header Background
I've created a simple example with Youtube video background using direct links to video stream (JS/CSS only solution). Feel free to check it on JSfiddle. Also, you can update public Google Image proxy URL to any public or your own CORS proxy.
var vid = "FUUw3zNTXH8",
streams,
video_tag = document.getElementById("video");
fetch("https://images" + ~~(Math.random() * 33) + "-focus-opensocial.googleusercontent.com/gadgets/proxy?container=none&url=" + encodeURIComponent("https://www.youtube.com/watch?hl=en&v=" + vid)).then(response => response.text()).then(function(data) {
if (data) {
streams = parse_youtube_meta(data);
video_tag.src = streams['hls'] || streams['720pna'] || streams['480pna'] || streams['720p'] || streams['480p'] || streams['360p'] || streams['240p'] || streams['144p'];
} else {
alert('Youtube API Error');
}
});
function parse_youtube_meta(rawdata) {
var regex = /(?:ytplayer\.config\s*=\s*|ytInitialPlayerResponse\s?=\s?)(.+?)(?:;var|;\(function|\)?;\s*if|;\s*if|;\s*ytplayer\.|;\s*<\/script)/gmsu;
rawdata = rawdata.split('window.getPageData')[0];
rawdata = rawdata.replace('ytInitialPlayerResponse = null', '');
rawdata = rawdata.replace('ytInitialPlayerResponse=window.ytInitialPlayerResponse', '');
rawdata = rawdata.replace('ytplayer.config={args:{raw_player_response:ytInitialPlayerResponse}};', '');
var matches = regex.exec(rawdata);
var data = matches && matches.length > 1 ? JSON.parse(matches[1]) : false;
console.log(data);
var streams = [],
result = {};
if (data.streamingData && data.streamingData.adaptiveFormats) {
streams = streams.concat(data.streamingData.adaptiveFormats);
}
if (data.streamingData && data.streamingData.formats) {
streams = streams.concat(data.streamingData.formats);
}
streams.forEach(function(stream, n) {
var itag = stream.itag * 1,
quality = false,
itag_map = {
18: '360p',
22: '720p',
37: '1080p',
38: '3072p',
82: '360p3d',
83: '480p3d',
84: '720p3d',
85: '1080p3d',
133: '240pna',
134: '360pna',
135: '480pna',
136: '720pna',
137: '1080pna',
264: '1440pna',
298: '720p60',
299: '1080p60na',
160: '144pna',
139: "48kbps",
140: "128kbps",
141: "256kbps"
};
//if (stream.type.indexOf('o/mp4') > 0) console.log(stream);
if (itag_map[itag]) result[itag_map[itag]] = stream.url;
});
if (data.streamingData && data.streamingData.hlsManifestUrl) {
result['hls'] = data.streamingData.hlsManifestUrl;
}
return result;
};
html, body {
height: 100%;
min-height: 100%;
background: #444;
overflow: hidden;
}
video {
width: 100%;
height: 100%;
object-fit: cover;
}
<video loop muted autoplay playsinline id="video"></video>
Related videos on Youtube
Thomas Smyth
Updated on June 27, 2022Comments
-
Thomas Smyth almost 2 years
I'm trying to create a few website templates to help me improve my front end development skills, as I'm currently far better at rear end work.
I'm trying to somewhat replicate the style of my own website (https://thomas-smyth.co.uk/), which is a simple Bootstrap template. However, instead of using a static photo in the header, I want to replace it with a Youtube video. I began by cutting down the template used in my website and have stripped it down to as little as I think I can get it without breaking the header.
I have found a few pieces of code around the place to show how to set a Youtube video as background of the overall page, but not the background for specific sections of the page. How can I do this? Note - It has to be streamed from YouTube as my hosts don't allow me to host video's on their servers.
My current code:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- Tell the browser to be responsive to screen width --> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"> <title>Group Name | Home</title> <!-- Bootstrap 3.3.6 --> <link rel="stylesheet" href="dist/bootstrap/css/bootstrap.min.css"> <!-- Font Awesome --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css"> <!-- Ionicons --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css"> <!-- Custom --> <link rel="stylesheet" href="dist/css/mainstyle.css"> </head> <body> <header> <div class="header-content"> <div class="header-content-inner"> <h1>This is going once vid is done.</h1> </div> </div> </header> <section class="bg-primary"> <div class="container"> <div class="row"> <div class="col-lg-8 col-lg-offset-2 text-center"> <h2 class="section-heading">Placeholder!</h2> <p>I should have found a witty comment to put here, but I'm just gonna put "Placeholder" instead.</p> </div> </div> </div> </section> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> <script src="dist/bootstrap/js/bootstrap.min.js"></script> <script src="dist/js/mainscript.js"></script> </body> </html>
CSS
html, body { height: 100%; width: 100%; } body { font-family: 'Merriweather', 'Helvetica Neue', Arial, sans-serif; } h1, h2, h3, h4, h5, h6 { font-family: 'Open Sans', 'Helvetica Neue', Arial, sans-serif; } p { font-size: 16px; line-height: 1.5; margin-bottom: 20px; } .bg-primary { background-color: #F05F40; } section { padding: 100px 0; } .no-padding { padding: 0; } header { position: relative; width: 100%; min-height: auto; background-image: url('../img/header.jpg'); background-position: 0% 80%; -webkit-background-size: cover; -moz-background-size: cover; background-size: cover; -o-background-size: cover; text-align: center; color: white; } header .header-content { position: relative; text-align: center; padding: 100px 15px 100px; width: 100%; } header .header-content .header-content-inner h1 { font-weight: 700; text-transform: uppercase; margin-top: 0; margin-bottom: 0; font-size: 30px; } @media (min-width: 768px) { header { min-height: 100%; } header .header-content { position: absolute; top: 50%; -webkit-transform: translateY(-50%); -ms-transform: translateY(-50%); transform: translateY(-50%); padding: 0 50px; } header .header-content .header-content-inner { max-width: 1000px; margin-left: auto; margin-right: auto; } header .header-content .header-content-inner h1 { font-size: 50px; } } .section-heading { margin-top: 0; } ::-moz-selection { color: white; text-shadow: none; background: #222222; } ::selection { color: white; text-shadow: none; background: #222222; } img::selection { color: white; background: transparent; } img::-moz-selection { color: white; background: transparent; } body { webkit-tap-highlight-color: #222222; }
Best I have so far (does whole page's background)
<div class="video-background"> <div class="video-foreground"> <iframe src="https://www.youtube.com/embed/W0LHTWG-UmQ?controls=0&showinfo=0&rel=0&autoplay=1&loop=1&playlist=W0LHTWG-UmQ" frameborder="0" allowfullscreen></iframe> </div> </div>
CSS
* { box-sizing: border-box; } .video-background { background: #000; position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: -99; } .video-foreground, .video-background iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; } @media (min-aspect-ratio: 16/9) { .video-foreground { height: 300%; top: -100%; } } @media (max-aspect-ratio: 16/9) { .video-foreground { width: 300%; left: -100%; } }
-
Thomas Smyth over 7 yearsThe current code does exactly that, or at least I tweaked it slightly to do that. I don't think it's actually possibly to stream a video as the background of a div/section of a page unless you use HTML Video player, which you cannot do with Youtube videos, so I have placed blank boxes over the background through the page to have different backgrounds elsewhere on the same page.
-
Thomas Smyth over 7 yearsI have yet to solve it, but have found a temporary way around it, which is a bit crude. If no one can answer my questions shortly, I will deem it no possible as that's the impression I have far from various articles and questions I have read.
-
350D almost 7 years@ThomasSmyth please, check my answer below
-
Shawn Rebelo over 6 yearsI freaken love you right now. Spending DAYS trying to figure this out. All examples are of full page! Just wrap in div element and all set.
-
Nicholas over 6 yearsSame story as @ShawnRebelo , you're awesome! The only thing I noticed is that it looks like the quality of the video is not as good (less smooth/crisp) as watching it directly on Youtube. Is there anything that could improve the quality? My youtube vid has 1080p50 . Maybe for the 50 fps a different tag is required?
-
350D about 6 years@Nicholas Hi. You can extend stream formats and add few more:
...298: '720p60na', 299: '1080p60na', 264: '1440pna'...
but all of these extra streams has no sound and takes longer to start playing. -
Nicholas about 6 years@350D thanks fory our answer, indeed I already found out that I can use 720p50na right now and now it plays fine. I think for some reason I temporarily did not get this streams and that's why I didn't find out immediately. I also saw that when on mobile and playing back the 1080p version it looks like it is zoomed in compared to the 720p version. Is there a way to change this?
-
350D about 6 years@Nicholas check your css for
video
tag ( support forobject-fit
on mobile) -
Gallex almost 6 yearshow to play it with sound? if i just remove muted from video tag, video stops playing
-
Gallex almost 6 years@350D fullscreen not working with edge, IE. at least in my desktop
-
Martin Braun almost 6 years@350D This also doesn't seem to work with YouTube streams: jsbin.com/fuvofunere/edit?html,css,js,output any idea why?
-
Nicholas over 5 yearsSince a few days the solution is not working anymore for my project. Not sure what's wrong I get a 404 in console..
-
Shawn Rebelo over 5 yearsTHIS OPTION IS NO LONGER WORKING DUE TO THE SERVICE BEING SHUT DOWN! Sorry for caps. But ya. Sadly this is no longer an option.
-
Frank over 5 years@ShawnRebelo I'm like you really love his answer and just found out today Yahool retired the service. Please see my answer below and hope it helps.
-
350D over 5 years@Nicholas Check my latest update with public Google image proxy! Works just fine!
-
Frank over 5 yearsThanks!!! I will delete my post. I used cors-anywhere.herokuapp.com for cors proxy.
-
350D over 5 years@Frank that one is ok for wireframes or POC projects. With google you can be safe for production with some caching
-
350D over 5 years@KeviinCosmos just echo your ID as javascript variable or
data
attribute for any element on the page specific to your widget for example. -
Keviin Cosmos over 5 years@350D Thanks - but i'm to green in this area. Do you have some links for me, to get in the right direction?
-
Keviin Cosmos over 5 years@350D IT WORKS! But i don't think it's the best solution: Screenshot link
-
coops about 5 years@350D Thank you SO MUCH, this has been bugging me for days/weeks!! This is a great solution and worked perfectly for me.
-
jessica about 5 years@350D any idea why a video might return error 150 with reason ""This video is unavailable." ? The video is public with embedding enabled.
-
Moorthy over 4 years@350D, Thanks for this great script. It was working fine but suddenly it stopped working and it showed this console error 'The play() request was interrupted by a call to pause().'. I have checked your demo and it is also not working now and showed same error. Any idea?. Thanks in advance.
-
350D over 4 years@Moorthy Hello! thank you for report! Snippet and JSFiddle example updated already. Youtube implemented new schema for some videos where no streams data available in json root.
-
jmchauv about 4 years@350D is there any way to add a 'startSeconds' parameter somewhere? I'd like my video to start 10 seconds in.
-
Martins almost 4 yearsThank you for this one dude. You rock!
-
Amaimersion over 3 years05.10.2020 - still working. Thank you for solution!
-
Zak over 3 years@Immersion how did you make it work? I'm getting an error in console. Something about CORS policy.
-
350D over 3 years@jmchauv two options here. 1 - add
loadedmetadata
event listener tovideo_tag
and setvideo_tag.currentTime = 5
. 2 - add#t=5,15
to the end of thevideo_tag.src
where first number = start, second end in seconds. }, false);