Search code examples
nativescript

Use YouTube Iframe API with Nativescript?


UPDATE: From @Manoj's code below and some other sources, I am now able to load the youtube player into a webview based on the Youtube iframe api. But the question still is: how can I have my app recognize when the video itself starts playing? (after the video loads, and after any ad plays).

The key code is "trapped" in the webview.

There is a nativescript-webview interface plugin that is meant to allow you to get information from the webview. If that is what is required here, what would be the correct code with that plugin to register when the video itself starts playing?

The examples on that plugin's repo seem pretty specific and different than what I have in mind here.


Original Question:

I have a Nativescript app using iOS and Angular. I would like to have youtube videos play in the app, and I want to be able to control the playback. So I want to do things like autoplay it programmatically and register when the video is actually playing.

How can I do this?

More Detail:

There is a nativescript-youtubeplayer plugin but i am not able to use that here, bc it requires an api key and some other reasons.

I am able to embed a basic iframe into a WebView, with code like this:

<WebView (loaded)="onWebViewLoaded($event)" requiresUserActionForMediaPlayback="false" [src]="urlSource"></WebView>

and in ts:

 public urlSource= '<iframe src="https://www.youtube.com/embed/ZwO3PG-c5Cs?playsinline=1&autoplay=1&fs=0&controls=1&enablejsapi=1"></iframe>'

This loads the video. But it does not have the normal youtube controls (like no big pause button on the video)--maybe bc its overridden by the webview. More importantly, it does NOT autoplay, and it does not give me a way to programmatically access the iframe info--so, for example, I am not able to tell when the video is actually playing vs when it is paused.

The Youtube Iframe Player API is made for this purpose, but how do I use it with Nativescript? It seems to require dom manipulation in a way that I have not seen Nativescript do before.

For example, the basic code for that is:

var player;
function onYouTubeIframeAPIReady() {
  player = new YT.Player('player', {
    height: '390',
    width: '640',
    videoId: 'M7lc1UVf-VE',
    events: {
      'onReady': onPlayerReady,
      'onStateChange': onPlayerStateChange
    }
  });
}

But, unsurprisingly, this brings up errors, like 'can't find name YT'.

So, how can I embed a youtube video in Nativescript with iframe and control it like I could if I had a web application?


Solution

  • I haven't looked at this for awhile, but thought it would be helpful to follow up to show what got this mostly working in my case. Hopefully there is some code in here that can help others.

    For me, the key insight was putting the basic youtube code (which they give you here) into a variable in the TS component:

    So, to start, my TS component put in the Youtube code like this:

    exportClass YoutubeComponent implements OnInit {
            public youtubeVideoId = [ID OF VIDEO I WANT TO PLAY]
            public youtubeCode = 
              `
               <!DOCTYPE html>
              <html>
              <body>
                 <!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
                   <iframe id="player"
                    width="90%" height="375"
                    src="https://www.youtube.com/embed/` + this.youtubeVideoId + `?enablejsapi=1&playsinline=1&autoplay=1&fs=0&controls=1" 
                frameborder="0"
                     ></iframe>
               <script>
               /**
               * WebViewInterface class to handle communication between webView and Android/iOS.
              */
             var NSWebViewinterface = (function () {
                   function NSWebViewinterface() {
             
              [PUT IN THE REST OF THE WHOLE YOUTUBE CODE IN THIS VARIABLE]
                 ...   
            `
    

    And then in html:

    <WebView row="0" src="{{youtubeCode}}" #webView></WebView> 
    

    And then to interact with the webview, in the same TS component as above:

     @ViewChild('webView') webView: ElementRef;
    
      onWebViewLoaded(args) {
         let webView: WebView = this.webView.nativeElement;
         this.oWebViewInterface = new WebViewInterface(webView); 
         this.nextFunction()
       }
    
      nextFunction {
         this.oWebViewInterface.on('onPlayerStateChange, (data) =>{
           if (data.state === 5){ //video cued
             console.log('video is cued up')
           }
        })
      }