Angular 8 - Is there a way to bind to a video element to determine when it is loaded/starts playing?

Viewed 5045

Given:

<video poster="assets/videos/poster.png"
       #videoPlayer 
       onloadedmetadata="this.muted = true">
     <source src="assets/videos/video.mp4" type="video/mp4">
</video>

And in Angular:

...

public videoLoaded: boolean = false;

...

How can I bind videoLoaded to update once the video starts playing? (or is loaded) I've looked online and saw some older jquery implementations that seem to not be working in newer versions of chrome and want to know the latest way on how to accomplish this

Thanks

2 Answers

What you could do is make a reference to the video player itself with Angular's ViewChild and check if it's clicked.

@ViewChild('videoPlayer') videoPlayer: ElementRef;

videoClicked = false;

startVideo(): void {
    this.videoClicked = true;
    this.videoPlayer.nativeElement.play();
}

The startVideo() method will be used inside the HTML to trigger the change. The additional paragraph is used to see the change.

<video (click)="startVideo()" width="400"
       #videoPlayer>
     <source src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" type="video/mp4">
</video>

<p>Video clicked: {{videoClicked}}</p>

See this StackBlitz as an example of above behaviour.

Edit
A better way to do this is to use HTMLMediaElement's onplaying and loadeddata event. See MDN for documentation on onplaying and documentation on onplaying. In normal JavaScript it would look like this:

const video = document.querySelector('video');

video.onplaying = (event) => {
  console.log('Video is no longer paused.');
};

In Angular, there are some small changes required. The HTML can stay pretty clean.

<video controls width="400"
       #videoPlayer>
     <source src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" type="video/mp4">
</video>

<p>Video loaded: {{dataLoaded}}</p>
<p>Video started: {{videoStarted}}</p>

The biggest changes are in the component, ngAfterViewInit checks if the element is there after view has been initialised. The loadeddata event is fired when the frame at the current playback position of the media has finished loading (so ready to play). Next to that, you can access the element's onplaying event to check if the video is not paused.

@ViewChild('videoPlayer') videoPlayer: ElementRef;

dataLoaded = false;
videoStarted = false;

ngAfterViewInit() {
    this.videoPlayer.nativeElement.onloadeddata = (event) => {
        console.log('Video data is loaded.');
        this.dataLoaded = true;
    };

    this.videoPlayer.nativeElement.onplaying = (event) => {
        console.log('Video is no longer paused.');
        this.videoStarted = true;
    };
}

Here's a StackBlitz example to show this example.

you can use HTML Audio/Video Events provided by html 5 video attribute.

loadeddata -> Fires when the browser has loaded the current frame of the audio/video

loadedmetadata -> Fires when the browser has loaded meta data for the audio/video

loadstart -> Fires when the browser starts looking for the audio/video

Related