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】:

我需要同时使用 onloadedmetadataoncanplay 来修复角度 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 组件名称吗?

为啥我无法访问 Angular 组件的传递函数内的类属性?

按下 Chrome 调试工具旋转到横向按钮时,Angular 组件会重新加载

如何在 Angular 中显示具有自己路由的父组件内的特定子组件?