MagicMirror Forum
    • Recent
    • Tags
    • Unsolved
    • Solved
    • MagicMirror² Repository
    • Documentation
    • 3rd-Party-Modules
    • Donate
    • Discord
    • Register
    • Login
    A New Chapter for MagicMirror: The Community Takes the Lead
    Read the statement by Michael Teeuw here.

    Controlling Embedded Youtube Video on MM

    Scheduled Pinned Locked Moved Troubleshooting
    23 Posts 6 Posters 14.3k Views 8 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Z Offline
      zichao92
      last edited by

      Hi all, im not too sure if i have made any mistake regarding the structure of MMM.

      I placed my notificationReceived at the front end of embedded youtube, which i called it youtube.js( it doesnt have any node_helper) :

      Here’s the code of my youtube.js , the codes are heavily based on a the default module called “compliments” :

      module.register("youtube",{
      
      	// Module config defaults.
      	defaults: {
      
      		updateInterval: 30000,
      		fadeSpeed: 4000
      	},
      
      
      
      	// Define required scripts.
      	getScripts: function() {
      		return ["moment.js"];
      //		exec("sudo python /home/pi/NicoRFID/RFID_playlist.py");
      	},
      	getStyles: function() {
      	    return [
      	        'script.css', // will try to load it from the vendor folder, otherwise it will load is from the module folder.
      	    ]
      	},
      
      	// Define start sequence.
      	start: function() {
      		Log.info("Starting module: " + this.name);
      
      		
      		// Schedule update timer.
      		var self = this;
      		setInterval(function() {
      			self.updateDom(self.config.fadeSpeed);
      		}, this.config.updateInterval);
      	},
      		
      
      		
      	/* randomIndex(compliments)
      	 * Generate a random index for a list of compliments.
      	 *
      	 * argument compliments Array - Array with compliments.
      	 *
      	 * return Number - Random index.
      	 */
      
      	/* complimentArray()
      	 * Retrieve an array of compliments for the time of the day.
      	 *
      	 * return compliments Array - Array with compliments for the time of the day.
      	 */
      	
      	/* complimentArray()
      	 * Retrieve a random compliment.
      	 *
      	 * return compliment string - A compliment.
      	 */
      		notificationReceived: function(notification, payload) {
      		if (notification === "PAUSE_VIDEO"){
      			pausethevideo()
      
      		}
      		else if (notification === "PLAY_VIDEO"){
      			playthevideo()
      
      		}
      	},
      
      
      	// Override dom generator.
      	getDom: function() {
      		//var complimentText = this.randomCompliment();
      		//var complimentText = "Hi NUS GOD Puay Hiang ";
      
      		//var compliment = document.createTextNode(complimentText);
      
      		var wrapper = document.createElement("div");
      		wrapper.className = "thin xlarge bright";
      
      		function playthevideo(){
      		var myPlayer = document.getElementById('my-video');
      		myPlayer.playVideo();
      		};
      
      		function stopthevideo(){
      		var myPlayer = document.getElementById('my-video');
      		myPlayer.stopVideo();
      		};
      
      		function pausethevideo(){
      		var myPlayer = document.getElementById('my-video'); 
      		myPlayer.pauseVideo();
      		};
      		
      		
      		wrapper.innerHTML='<div> <div> allowfullscreen></div></div>';
      
      		
      
      		
      
      			
      		//wrapper.appendChild(compliment);
      
      		return wrapper;
      	}
      
      });
      

      So with the notificationReceived line, i intend to control my video using the remote control with these codes :

      / edit menu buttons
              "show-all-button": function() {
              var parent = document.getElementById("visible-modules-results");
              var buttons = parent.children;
              for (var i = 0; i < buttons.length; i++) {
               if (buttons[i].id!="module_5_youtube"){
                  if (Remote.hasClass(buttons[i], "external-locked")) {
                      continue;
                  }
                  buttons[i].className = buttons[i].className.replace("toggled-off", "toggled-on");
                  Remote.showModule(buttons[i].id);
                  var notification = "PAUSE_VIDEO";
                  Remote.getWithStatus("action=NOTIFICATION&n"+"otification=" + notification );
                  }
              else{
                      if (Remote.hasClass(buttons[i], "external-locked")) {
                      continue;
                  }
                  buttons[i].className = buttons[i].className.replace("toggled-on", "toggled-off");
                  Remote.hideModule(buttons[i].id);
                              }
      

      Am i doing something wrong here?

      1 Reply Last reply Reply Quote 0
      • Z Offline
        zichao92 @Jopyth
        last edited by

        @Jopyth ,

        I managed to have some developments with your remote control module’s sendNotifcation command. I hooked up the MM using a browser and observed( using dev console, Note to beginners: press F12 on a browser to access this cool feature ) that a notification was send from MM Remote. This means that you were right all along, just that i didnt know how to observe the sendNotification command via dev console.

        Currently, i have another issue. My youtube.js module receives the “PLAY_VIDEO” or “PAUSE_VIDEO” notification but is not able to perform what was desired.

        Here’s my snippet of my code from my youtube.js :

        notificationReceived: function(notification, payload) {
        		if (notification === "PAUSE_VIDEO"){
        			pausethevideo()
        
        		}
        		if (notification === "PLAY_VIDEO"){
        			playthevideo()
        
        		}
        	},
        
        getDom: function() {
        var wrapper = document.createElement("div");
        		wrapper.className = "thin xlarge bright";
        
        		function playthevideo(){
        		var myPlayer = document.getElementById('my-video');
        		myPlayer.playVideo();
        		};
        
        		function stopthevideo(){
        		var myPlayer = document.getElementById('my-video');
        		myPlayer.stopVideo();
        		};
        
        		function pausethevideo(){
        		var myPlayer = document.getElementById('my-video'); 
        		myPlayer.pauseVideo();
        		};
        		
        		
        		wrapper.innerHTML='<div> <div> allowfullscreen></div></div>'; //youtube video link found here.
        
        		
        
        			return wrapper;
        	}
        
        });
        

        However, i got an error from dev console :
        Uncaught TypeError: Cannot read property 'pauseVideo' of null at Class.notificationReceived (youtube.js:69)

        Im suspecting that my pauseVideo/playVideo function wasn’t recognised as it is getDom.

        Will appreciate any help or advice !

        strawberry 3.141S 1 Reply Last reply Reply Quote 0
        • strawberry 3.141S Offline
          strawberry 3.141 Project Sponsor Module Developer @zichao92
          last edited by

          @zichao92 the access to those functions is limited to the getDom function.

          you should put the definitions outside like

          playthevideo: function() {
          //do the stuff
          }
          

          and call the function like this.playthevideo()

          Please create a github issue if you need help, so I can keep track

          Z 1 Reply Last reply Reply Quote 0
          • Z Offline
            zichao92 @strawberry 3.141
            last edited by zichao92

            @strawberry-3.141 said in Controlling Embedded Youtube Video on MM:

            playthevideo: function() {
            //do the stuff
            }

            Hi there,

            I tried your recommendation but i got this error Uncaught TypeError: Cannot read property 'playVideo' of null.
            Which is coming from this code:

            playthevideo: function() {
            		var myPlayer = document.getElementById('my-video');
            		myPlayer.playVideo();
            		},
            

            I suspect that the problem is that the above function is not being recognise as my embedded youtube codes still lies in the getDom function, which has the allowscriptaccess="awalys" that allows the user to control the video. I tried to extract out from the getDom function but i think my syntax is wrong. Here’s the full code of the youtube function that’s in the getDom function.

            		wrapper.innerHTML='<div> <div>  //(youtube link here ) controls=0&showinfo=0&rel=0&autoplay=1" allowscriptaccess="always" name="my-video" frameborder="0" enablejsapi=1&version=3&playerapiid=ytplayer" type="application/x-shockwave-flash"> allowfullscreen></div></div>';
            
            strawberry 3.141S 1 Reply Last reply Reply Quote 0
            • strawberry 3.141S Offline
              strawberry 3.141 Project Sponsor Module Developer @zichao92
              last edited by

              @zichao92 because there is no html element that has the id your looking for so var myPlayer = document.getElementById('my-video'); is null

              Please create a github issue if you need help, so I can keep track

              Z 1 Reply Last reply Reply Quote 0
              • Z Offline
                zichao92 @strawberry 3.141
                last edited by

                Hi @strawberry-3.141 ,
                Thanks for the clarification!
                I have added id = "my-vdieo" into my code, however, it produced another error :

                Uncaught TypeError: myPlayer.playVideo is not a function
                    at Class.playthevideo (youtube.js:69)
                

                It’s not able to detect the function. After doing some readings about embedded YouTube videos, i came across this site :
                https://developers.google.com/youtube/js_api_reference#onYouTubePlayerReady

                It was mentioned that i require a callback function named onYouTubePlayerReady. The API will call this function when the player is fully loaded and the API is ready to receive calls.

                From there, I should be able to control my video. However, since this function can only be called in getDom function, im not too sure how it should work from here.

                strawberry 3.141S 1 Reply Last reply Reply Quote 0
                • strawberry 3.141S Offline
                  strawberry 3.141 Project Sponsor Module Developer @zichao92
                  last edited by

                  @zichao92 do you have your code on github?

                  Please create a github issue if you need help, so I can keep track

                  Z 1 Reply Last reply Reply Quote 0
                  • Z Offline
                    zichao92 @strawberry 3.141
                    last edited by zichao92

                    Hi @strawberry-3.141 ,

                    I just uploaded to github ( not too sure if i have done it correctly , first time using github) but here you go.

                    https://github.com/zichao92/youtube/tree/Remote-

                    Edit 1: I’m still using an older version of Remote Control module by Jopyth, it’s more stable on my MagicMirror( less laggy etc). Im not too sure why though

                    strawberry 3.141S 1 Reply Last reply Reply Quote 0
                    • strawberry 3.141S Offline
                      strawberry 3.141 Project Sponsor Module Developer @zichao92
                      last edited by

                      @zichao92 I cleaned up your module

                      Module.register("youtube",{
                      
                          start: function() {
                              Log.info("Starting module: " + this.name);
                          },
                      
                          getStyles: function() {
                              return ['script.css'];
                          },
                      
                          sendCommand: function(cmd){
                              var myPlayer = document.getElementById('my-video');
                              if(myPlayer){
                                  myPlayer.contentWindow.postMessage(JSON.stringify({
                                      "event": "command",
                                      "func": cmd
                                  }), "*");
                              }
                          },
                      
                          notificationReceived: function(notification, payload) {
                              if (notification === "PAUSE_VIDEO"){
                                  this.sendCommand("pauseVideo");
                              }
                              if (notification === "PLAY_VIDEO"){
                                  this.sendCommand("playVideo");
                              }
                          },
                          
                          getDom: function() {
                      
                              var wrapper = document.createElement("div");
                      
                              var background = document.createElement("div");
                              background.classList.add("video-background");
                      
                              var foreground = document.createElement("div");
                              foreground.classList.add("video-foreground");
                      
                              var iframe = document.createElement("iframe");
                              iframe.setAttribute("id", "my-video");
                              iframe.setAttribute("src", "https://www.youtube.com/embed/5kIe6UZHSXw?enablejsapi=1&autoplay=1");
                              iframe.setAttribute("frameborder", "0");
                              iframe.setAttribute("type", "text/html");
                      
                              foreground.appendChild(iframe);
                              background.appendChild(foreground);
                              wrapper.appendChild(background);
                      
                              return wrapper;
                          }
                      });
                      

                      Please create a github issue if you need help, so I can keep track

                      Z E 2 Replies Last reply Reply Quote 1
                      • Z Offline
                        zichao92 @strawberry 3.141
                        last edited by

                        @strawberry-3.141

                        OMG you are life saver. So the whole trick to my module is to use sendcommand instead?

                        strawberry 3.141S 1 Reply Last reply Reply Quote 0
                        • 1
                        • 2
                        • 3
                        • 2 / 3
                        • First post
                          Last post
                        Enjoying MagicMirror? Please consider a donation!
                        MagicMirror created by Michael Teeuw.
                        Forum managed by Sam, technical setup by Karsten.
                        This forum is using NodeBB as its core | Contributors
                        Contact | Privacy Policy