Chrome (Android) video autoplay inside Angular 2+ component

孤人 提交于 2020-01-10 03:13:51

问题


What does not work:

If I put a video tag with "autoplay" (see below) into the template of an Angular 2+ component with the goal of autoplaying on mobile:

<video muted autoplay>
    <source src="path/to/video.mp4" type="video/mp4" />
</video>

What does work:

  • Moving it to the index.html (outside of the Angular component)
  • Appending it to the body from within the component:

    window.addEventListener('load', () => {
        document.body.innerHTML += "<video autoplay muted loop>\n" +
                                   "    <source src=\"path/to/video.mp4\" type=\"video/mp4\" />\n" +
                                   "</video>";
    });
    
  • Including the video in the component's template, enabling the "user controls", and manually touching the play button on the video (i.e. no autoplay)

Theories:

I don't think it's an issue of an invalid path to the video, since I'm able to manually click the "play" button.

According to here and here, autoplay on mobile should be allowed if (1) the video is muted, and (2) the video is "visible". I've read that "visible" in this context is more or less defined to mean "attached to DOM" and not "display: none" in at least a couple of places.

My best theory is that Angular 2+ is sticking the component in some kind of "Shadow DOM" (or similar) that's resulting in mobile Chrome not thinking that it's visible. I tried setting the component to encapsulation: ViewEncapsulation.None to see if that made a difference, but same result.

Additionally, if I try to set an event listener against the "loaded" or "canplaythrough" events and manually call videoElement.play(), then I get: DOMException: play() can only be initiated by a user gesture. If I make the same function call in the devtools console (tethering to mobile device via USB), then it does play.

Final thoughts:

It seems that Angular is likely what's getting in my way. Is there any known Angular setting or workaround I can leverage to get a video to autoplay within an Angular 2+ component on Android Chrome? Thanks for any help.

(p.s.: there's like a million questions on S.O. and elsewhere about autoplaying video on mobile Chrome, but none of them seem to address the issue of doing it within an Angular component or similar)


回答1:


Answer and work-around to OP and to question in my own comment: Yes, appending a video tag as vanilla HTML to an already initialized Angular component works as expected (confirmed at least in Chrome & FF). Just happened to need this for my own project today. :)

So you can do something like this, or a pipe that returns the HTML for a given video URL (which is much better perf-wise, google "Angular Pipes").

<div *ngFor="let file of files" [innerHTML]="getVideoTag(file)"></div>

// component
  getVideoTag(file) {
    return this.domSanitizer.bypassSecurityTrustHtml(
      `<video width="1280" height="720" autoplay muted controls>
          <source src="${file.url}" type="video/mp4">No HTML5 supported.</source>
       </video>`
    );
  }



回答2:


I was searching for this issue a lot and I put the muted attribute like this:

[muted]="true" rather than just muted

and now it works

<video [muted]="true" autoplay>
    <source src="path/to/video.mp4" type="video/mp4" />
</video>

Chrome has a policy to not let videos autoplay if the user has not first interacted with the page however if its a muted video chrome allows it. The problem here is that for some reason muted value goes as false when you just put muted in angular.




回答3:


Similar issue with Angular 6 and Chrome 70.

In fact, the muted attribute in the HTML seems to be ignored by Chrome when the video is added by Angular. The resulting DOM element has a 'muted' property set to 'false'. Not sure if it is an Angular or a Chrome bug.

You need to set it manually to true to make the autoplay work.

I ended up with a directive :

@Directive({selector: '[my-autoplay]' })
export class AutoplayVideoDirective implements OnInit {

  constructor(public element: ElementRef) { }

  public ngOnInit(): void {
    let vid = this.element.nativeElement;
    vid.muted = true;
    vid.play();
  }
}

and the HTML :

<video loop muted autoplay my-autoplay>



回答4:


I needed to use both onloadedmetadata and oncanplay to fix in angular 6

<video id="bg-video" loop muted autoplay oncanplay="this.play()" onloadedmetadata="this.muted = true">
    <source src="video.mp4" type="video/mp4">
</video>



回答5:


Had a similar issue with Chrome 66 (OSX High Sierra) not autoplaying a muted video in a Mat Dialog being opened by its parent on init. Solved it by adding *ngIf="true" to the video element:

<video *ngIf="true" autoplay muted onloadedmetadata="this.muted = true" controls>
    <source src="myVid.mp4" type="video/mp4">
    <p>Your browser does not support the video element.</p>
</video>


来源:https://stackoverflow.com/questions/48856562/chrome-android-video-autoplay-inside-angular-2-component

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!