Youtube Video Header Background

16,711

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>
Share:
16,711

Related videos on Youtube

Thomas Smyth
Author by

Thomas Smyth

Updated on June 27, 2022

Comments

  • Thomas Smyth
    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
    Thomas Smyth over 7 years
    The 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
    Thomas Smyth over 7 years
    I 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
    350D almost 7 years
    @ThomasSmyth please, check my answer below
  • Shawn Rebelo
    Shawn Rebelo over 6 years
    I 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
    Nicholas over 6 years
    Same 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
    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
    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
    350D about 6 years
    @Nicholas check your css for video tag ( support for object-fit on mobile)
  • Gallex
    Gallex almost 6 years
    how to play it with sound? if i just remove muted from video tag, video stops playing
  • Gallex
    Gallex almost 6 years
    @350D fullscreen not working with edge, IE. at least in my desktop
  • Martin Braun
    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
    Nicholas over 5 years
    Since 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
    Shawn Rebelo over 5 years
    THIS 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
    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
    350D over 5 years
    @Nicholas Check my latest update with public Google image proxy! Works just fine!
  • Frank
    Frank over 5 years
    Thanks!!! I will delete my post. I used cors-anywhere.herokuapp.com for cors proxy.
  • 350D
    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
    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
    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
    Keviin Cosmos over 5 years
    @350D IT WORKS! But i don't think it's the best solution: Screenshot link
  • coops
    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
    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
    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
    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
    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
    Martins almost 4 years
    Thank you for this one dude. You rock!
  • Amaimersion
    Amaimersion over 3 years
    05.10.2020 - still working. Thank you for solution!
  • Zak
    Zak over 3 years
    @Immersion how did you make it work? I'm getting an error in console. Something about CORS policy.
  • 350D
    350D over 3 years
    @jmchauv two options here. 1 - add loadedmetadata event listener to video_tag and set video_tag.currentTime = 5. 2 - add #t=5,15 to the end of the video_tag.src where first number = start, second end in seconds. }, false);