问题
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