Search code examples
javascripthtmliframeyoutube-api

How to make one button play several youtube videos in embedded iframes?


I have a few youtube videos embedded in a couple of iframes, and would like to start stop all the videos at once, using only one button. I've tried a few different methods, but just couldn't get it right.

Here is what I got.

main.html:

<!DOCTYPE html>
<html>
<head>
    <title>YT Mosaic</title>
    <link href="main.css" rel="stylesheet">
</head>

<body>

<!-- begin snippet: js hide: false console: true babel: false -->

<div class="container">
    <div class="mosaic">
        <iframe id="if1" src="https://www.youtube.com/embed/5mL-OkdM7Tc?cc_load_policy=3&autoplay=0&mute=1&enablejsapi=1" frameborder="0" allowfullscreen></iframe> <!-- TRT -->
        <iframe id="if2" src="https://www.youtube.com/embed/9Auq9mYxFEE?cc_load_policy=3&autoplay=0&mute=1&enablejsapi=1" frameborder="0" allowfullscreen></iframe> <!-- SKY -->
        <iframe id="if3" src="https://www.youtube.com/embed/VBTdNwm5CDY?cc_load_policy=3&autoplay=0&mute=1&enablejsapi=1" frameborder="0" allowfullscreen></iframe> <!-- Global News -->
        <iframe id="if4" src="https://www.youtube.com/embed/ntmPIzlkcJk?cc_load_policy=3&autoplay=0&mute=1&enablejsapi=1" frameborder="0" allowfullscreen></iframe> <!-- Euronews -->
        <iframe id="if5" src="https://www.youtube.com/embed/GE_SfNVNyqk?cc_load_policy=3&autoplay=0&mute=1&enablejsapi=1" frameborder="0" allowfullscreen></iframe> <!-- DW -->
        <iframe id="if6" src="https://www.youtube.com/embed/h3MuIUNCCzI?cc_load_policy=3&autoplay=0&mute=1&enablejsapi=1" frameborder="0" allowfullscreen></iframe> <!-- F24 -->        
    </div>

    <button onclick="iframe1play(); return false;">⏯️</button>
    <button onclick="stop();">⏹</button>
    <button onclick="playAll();">▶▶ Play All</button>
</div>

<script>

    var tag = document.createElement('script');
    tag.src = "https://www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

    var ifa  = [];       // array of iframe id's
    var ifos = [];       // array of iframe YT objects for use elsewhere

    // For each iframe you find, add its ID to the ifa array
    var iframes = document.querySelectorAll("div.mosaic iframe");
    iframes.forEach(function(iframe) {
        ifa.push(iframe.id);
    });
    console.log('[LOG] iframe array:', ifa)
    // Array(6) [ "if1", "if2", "if3", "if4", "if5", "if6" ]

    // Once the YouTube API is ready, for each iframeId in your array, 
    // create a new YT player and give it the onReady event.
    function onYouTubeIframeAPIReady() {
        ifa.forEach(function(iframeId) {
            var player = new YT.Player(iframeId, {
                events: {
                    'onReady': onPlayerReady,
                }
            });
        });
    }

    function onPlayerReady(event) {
        var ifo = event.target;

        ifos.push(ifo);                 // Push current iframe object to ifo array
        ifos.forEach(function(j) {
            j.setVolume(30);
            j.playVideo();
            j.unMute();
        });
    }
    
    var player;
    // WARNING this need to be commented out as it interferes with the other version.
    function onYouTubeIframeAPIReady() {
        player = new YT.Player('if1', {
            events: {
                'onReady': onPlayerReady,
                'onStateChange': onPlayerStateChange,
                'onError': catchError
            }
        });
    }

    var done = false;
    function onPlayerStateChange(event) {
        if (event.data == YT.PlayerState.PLAYING && !done) {
            setTimeout(stopVideo, 6000);    // wait 6 s. before stopping player
            done = true;
        }
    }
    
    function catchError(event) {
        if (event.data == 2)   console.log("[LOG] Error: The request contains an invalid parameter value.");
        if (event.data == 5)   console.log("[LOG] Error: content cannot be played in an HTML5 player.");
        if (event.data == 100) console.log("[LOG] Error: Video doesn't exists (or has been removed)!");
        if (event.data == 101) console.log("[LOG] Error: Not allowed to be played in an embedded player.");
        if (event.data == 150) console.log("[LOG] Error: Not allowed to be played in an embedded player.");
        // This should never happen!
        console.log("Error:\n", event);
    }

    // This was a test, not working, trying to use:
    // onload="p1=new YT.Player(this);">
    function playAll() {
        var ifs = [p1,p2,p3,p4,p5,p6];
        for(var i=0; i<ifs.length; i++) {
            console.log("Try to Play: ", toString(ifs[i]));
            ifs[i].playVideo();
        }
    }

    function play() {
        //player.unMute();
        player.playVideo();
        //show_video_url();
    }
    function pause() {       player.pauseVideo();   }
    function stop() {        player.stopVideo();    }
    function stopVideo() {   player.stopVideo();    }
    function mute() {        player.unMute();       }

    function iframe1play() {
        if (player.getPlayerState() == YT.PlayerState.PLAYING) {
            player.pauseVideo();
            document.getElementById("if1").style.opacity = "0.7";
        } else {
            player.playVideo();
            document.getElementById("if1").style.opacity = "1";
        }
    }

</script>

</body>
<footer>FTSE</footer>

</html>

and here is the CSS file main.css:

body {
    background-color: #404040;
    color: lightgrey;
    margin: 0;
    padding: 1em;
    /*height: 100vh;*/
    box-sizing: border-box;
}

.container {
    max-width: 1100px;  
    /*  width: 100%;*/
    border: 1px solid black;
    padding: 10px;
}

.mosaic {
    display: grid;
    /* Setup a 2x3 frame: */
    /* fr is a fractional unit and 1fr is for 1 part of the available space */
    grid-template-columns: 1fr 1fr;
    grid-template-rows:    50% 50% 50%;
    /*grid-template-rows:  1fr 1fr 1fr;*/
    max-width: 1100px;              /* 100% */
    max-height: 100%;               /* 100% */
    /*aspect-ratio: 16/9;*/         /* 16/9 */ 
    /* margin: auto; */             /* auto */
    margin-bottom: 1em;             /* 1em */
    /*padding: 2em; */
    gap: 5px;                       /* 1em */
}

iframe {
    /* iframe width="560" height="315" */
    display: block;
    width:  100%;
    height: 100%;
    aspect-ratio: 16/9;             /*  */ 
    /*min-width: 350px;*/           /* 350px */
    /*min-height: 200px;*/          /* 200px */
    background: gray;             /* yellow */ 
    border: 1px solid black;      /* border: solid red */
    margin: 0px;                    /*  */
}

How can I use the iframe id= tag to start all iframe videos using one button?

  • preferably using JS without additional libraries, such as jQuery.

  • JSfiddle code


Solution

  • You can use Youtube's IFrame Player API. They have a great documentation here https://developers.google.com/youtube/iframe_api_reference

    You can basically control all youtube embed videos by generating it through their API.

    A working sample would be down below:

    <body>
           <div id="container">
            <div id="player-5mL-OkdM7Tc"></div> <!-- TRT -->
            <div id="player-9Auq9mYxFEE"></div> <!-- SKY -->
            <div id="player-VBTdNwm5CDY"></div> <!-- Global News -->
            <div id="player-ntmPIzlkcJk"></div> <!-- Euronews -->
            <div id="player-GE_SfNVNyqk"></div> <!-- DW -->
            <div id="player-h3MuIUNCCzI"></div> <!-- F24 --> 
           </div>
    
           <button onclick="play()">
             Play All
           </button>
            <script src="https://www.youtube.com/iframe_api"></script>
            <script src="main.js" async defer></script>
    </body>
    
    let playersObjs = [];
    
    window.onYouTubeIframeAPIReady = () => {
        const playerContainers = document.querySelectorAll('div[id^="player"]');
    
    
        playerContainers.forEach((container) => {
            const videoId = container.id.slice(7);
    
            playersObjs.push(new YT.Player(container.id, {
                height: '200',
                width: '100',
                videoId,
                playerVars: {
                    'playsinline': 1
                }
            }))
        })
    }
    
    const play = () => {
        playersObjs.forEach((player) => {
            player.playVideo();
        })
    }