Search code examples
javascriptiframeyoutubevolume

How to execute volume changes on a youtube iframe from javascript?


JS/HTML noob here, please bear with me.

I have an html page containing an iframe. https://developers.google.com/youtube/iframe_api_reference#Example_Video_Player_Constructors I'm using the example in the 'GettingStarted' section above and testing on JSFiddle.

I want to be able to execute volume changes on the youtube player after the page has loaded.

The youtube API's setVolume function works from within the HTML page (I can successfully load the page and set the volume using the information in the docs), but I'm struggling to figure out how to call/expose that outside of the page.

I've figured out a way to do this by adding buttons to the page, see my answer below, and please let me know if there are better approaches! Thanks


Solution

  • I have figured this out by using buttons to call the functions I need access to. Here's the HTML from youtube with the buttons added:

      <body>
      
      <button id="mutebutton" onclick = "mute()" > Mute </button>
      <button id= "unmutebutton" onclick = "unmute()" > UnMute </button>
        <!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
        <div id="player"></div>
    
        <script>
          // 2. This code loads the IFrame Player API code asynchronously.
          var tag = document.createElement('script');
    
          tag.src = "https://www.youtube.com/iframe_api";
          var firstScriptTag = document.getElementsByTagName('script')[0];
          firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
    
          // 3. This function creates an <iframe> (and YouTube player)
          //    after the API code downloads.
          var player;
          function onYouTubeIframeAPIReady() {
            player = new YT.Player('player', {
              height: '390',
              width: '640',
              videoId: 'M7lc1UVf-VE',
              playerVars: {
                'playsinline': 1
              },
              events: {
                'onReady': onPlayerReady,
                'onStateChange': onPlayerStateChange
              }
            });
          }
    
          // 4. The API will call this function when the video player is ready.
          function onPlayerReady(event) {
            event.target.playVideo();
          }
    
          // 5. The API calls this function when the player's state changes.
          //    The function indicates that when playing a video (state=1),
          //    the player should play for six seconds and then stop.
          var done = false;
          function onPlayerStateChange(event) {
            if (event.data == YT.PlayerState.PLAYING && !done) {
              setTimeout(stopVideo, 6000);
              done = true;
            }
          }
          
          function mute(){
          player.mute();
          }
          
          function unmute(){
          player.unMute();
          }
          
          function stopVideo() {
            player.stopVideo();
          }
        </script>
      </body>
    </html>
    

    And the javascript to run:

    const button = document.getElementById('mutebutton'); 
    
    setTimeout(function() { 
        button.click();
    }, 5000); 
    

    Timeout is there to ensure everything is fully loaded. Testing this in jsFiddle mutes the video after 5 seconds.

    So this gets me a lot of the way with setting volume. My main issue now is that it would be ideal to be able to pass a parameter to increase/decrease the volume to a specific value.