Angular 2+ 组件内的 Chrome (Android) 视频自动播放
Posted
技术标签:
【中文标题】Angular 2+ 组件内的 Chrome (Android) 视频自动播放【英文标题】:Chrome (Android) video autoplay inside Angular 2+ component 【发布时间】:2018-07-29 02:54:34 【问题描述】:什么不起作用:
如果我将带有“自动播放”的视频标签(见下文)放入 Angular 2+ 组件的模板中,目标是在移动设备上自动播放:
<video muted autoplay>
<source src="path/to/video.mp4" type="video/mp4" />
</video>
做什么工作:
将其移至 index.html(Angular 组件之外)从组件内将其附加到正文:
window.addEventListener('load', () =>
document.body.innerHTML += "<video autoplay muted loop>\n" +
" <source src=\"path/to/video.mp4\" type=\"video/mp4\" />\n" +
"</video>";
);
在组件的模板中包含视频,启用“用户控件”,并手动触摸视频上的播放按钮(即不自动播放)
理论:
我认为这不是视频路径无效的问题,因为我可以手动点击“播放”按钮。
根据here 和here,如果 (1) 视频已静音,并且 (2) 视频“可见”,则应允许在移动设备上自动播放。我读过,在这种情况下,“可见”或多或少被定义为“附加到 DOM”,而不是“显示:无”,至少在几个地方。
我最好的理论是 Angular 2+ 将组件粘贴在某种“Shadow DOM”(或类似的)中,导致移动 Chrome 不认为它是可见的。我尝试将组件设置为 encapsulation: ViewEncapsulation.None
以查看是否有所不同,但结果相同。
此外,如果我尝试针对“加载”或“canplaythrough”事件设置事件侦听器并手动调用videoElement.play()
,那么我会得到:DOMException: play() can only be initiated by a user gesture
。如果我在 devtools 控制台中进行相同的函数调用(通过 USB 连接到移动设备),那么它会播放。
最后的想法:
看来 Angular 可能是我遇到的问题。我可以利用任何已知的 Angular 设置或解决方法来让视频在 android Chrome 上的 Angular 2+ 组件中自动播放吗?感谢您的帮助。
(p.s.:在 S.O. 和其他地方有大约一百万个关于在移动 Chrome 上自动播放视频的问题,但似乎都没有解决在 Angular 组件或类似组件中执行此操作的问题)
【问题讨论】:
我认为你的理论是正确的,元素被创建并尝试在进入 dom 之前自动播放。您是否尝试过将视频标签附加到 ngOnInit 中的组件,或者可能只设置自动播放并在此时附加源标签? 【参考方案1】:我一直在寻找这个问题,我把 muted 属性设置为:
[muted]="true"
而不仅仅是muted
现在可以了
<video [muted]="true" autoplay>
<source src="path/to/video.mp4" type="video/mp4" />
</video>
Chrome 有一个政策,如果用户没有首先与页面交互,但如果它的静音视频 chrome 允许,则不允许视频自动播放。这里的问题是,由于某种原因,当您将 muted
放入角度时,静音值会变为 false。
【讨论】:
绝对 [muted]="true" 完美运行。谢谢@Dilshan Liyanage【参考方案2】:我需要同时使用 onloadedmetadata
和 oncanplay
来修复角度 6
<video id="bg-video" loop muted autoplay oncanplay="this.play()" onloadedmetadata="this.muted = true">
<source src="video.mp4" type="video/mp4">
</video>
【讨论】:
这是我尝试其他几种解决方案时唯一的解决方案。非常感谢@tommybananas【参考方案3】:Angular 6 和 Chrome 70 的类似问题。
事实上,当 Angular 添加视频时,HTML 中的 muted 属性似乎被 Chrome 忽略了。生成的 DOM 元素的“静音”属性设置为“假”。不确定是 Angular 还是 Chrome 错误。
您需要手动将其设置为 true 才能使自动播放生效。
我最终得到了一个指令:
@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();
和 HTML :
<video loop muted autoplay my-autoplay>
【讨论】:
有趣的解决方案 - 我喜欢它! 执行 vid.play() 时出现错误。视频好像没有这个功能。我在 Angular 10 中使用 Firefox。ERROR TypeError: vid.play is not a function at VideoAutoplayMutedDirective.ngOnInit
【参考方案4】:
Chrome 66 (OSX High Sierra) 也有类似的问题,它无法在其父级在初始化时打开的 Mat 对话框中自动播放静音视频。通过将*ngIf="true"
添加到视频元素来解决它:
<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>
【讨论】:
【参考方案5】:回答和解决 OP 并在我自己的评论中提出问题:是的,将视频标签作为 vanilla HTML 附加到已经初始化的 Angular 组件可以按预期工作(至少在 Chrome 和 FF 中得到确认)。今天恰好需要这个用于我自己的项目。 :)
所以你可以做这样的事情,或者一个返回给定视频 URL 的 HTML 的管道(这在性能方面要好得多,谷歌“Angular Pipes”)。
<div *ngFor="let file of files" [innerHTML]="getVideoTag(file)"></div>
// component
getVideoTag(file)
return this.domSanitizer.bypassSecurityTrustHtml(
`<video autoplay muted controls>
<source src="$file.url" type="video/mp4">No HTML5 supported.</source>
</video>`
);
【讨论】:
虽然对我来说,每次我的组件输入之一发生变化时它都会替换视频。不过,我可能可以做类似的事情。 所以,是的,如果我接受您评论中的建议(从 ngInit 将子项附加到 DIV),那么它可以完美运行。 啊,是的,就是模板中的那个函数调用,它会在每次更改检测时运行。摆脱它,我举了一个不好的例子:D 我的组件仅在 mat-dialog 中使用,所以不是问题 - 没有输入。以上是关于Angular 2+ 组件内的 Chrome (Android) 视频自动播放的主要内容,如果未能解决你的问题,请参考以下文章
formGroup的子组件内的Angular 2 formControlName
如何在 Chrome 开发人员工具中将 CSS 样式更改保存到 ANGULAR 2.0 组件表单?
Chrome 开发工具可以帮助找出 Angular 组件名称吗?