先从两个 browser 异常 log 说起
异常场景A
Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first.
异常场景B
File chooser dialog can only be shown with a user activation.
场景A分析
触发源码
var audio = document.getElementById('audio');
audio.play();
触发场景
需求为进入页面后,自动播放背景音乐,此时我们获取到了具有src
的audio元素,进行播放,进行常规逻辑,但是在播放的时候却出现异常,对应上面场景A的log,此时点击播放却可以进行正常播放
分析原因
自动播放 HTMLMediaElement => Audio / Video, 此类资源如果自动播放对用户来说会造成用户很苦恼,联想此类场景大家可能经历过在微信中打开一个视频,突然发出不雅的声音,联想到此场景,你可能已经感受到浏览器api在设计当初的一丝细致感,不仅仅是 audio, video,还有 web audio api 也存在相同的设计哲学
更进一步
那从上面的log中能得到那些信息呢,直译即为
用户还未与文档发生交互,不能进行播放行为
回到重点上,文中有几个关键字
- 用户
- 文档交互
- 播放
我们进行简单逻辑转换
用户 => 交互 => 可播放
再进行转换后的逻辑抽象,并提取重要概念
文档交互
那意思是我们在文档没有交互的时候进行了文档需要交互才能执行的行为,比如我们问题的出发点, audio 播放行为,为了知其然知其所以然,我们进行了部分实验以获取更进一步的信息,分别对两个标签进行测试,标签如下
<audio src='cd.mp3' id='audio'></audio>
<input type='file' id='file' />
在探索过程中了解了一些基本的特性,但是还是没有探索到最终的机制,感觉是围绕 isTrusted 属性的一些应用
有一些基本实事:
-
user interact 和 用户的 user activation 是不一样的两个概念
-
user activation 更为苛刻
-
user activation 存在时间限制,例如点击后3秒内属于 user activation 状态,存在定时器
-
user interact 是一种持久状态
-
移动端的策略和PC端是有区别的
-
IOS和 Android 也有区别
-
存在一些关键字
- auto play policy
- activation
- DOMActivate Events
- Event.isTrusted
-
能够激活的两者的事件有: tap, click, mousedown, mouseup, keydown, keyup (并不限于此,这些是监听document得到的)
思考
浏览器设计哲学中定义了每个他们能够想到的场景,例如安全问题,干扰人的因素,而且不同的厂商之间是对某些问题没有达成一致的,例如 ios 获取 video 首帧问题, Android是能够获取到的,但是ios是不能获取到的,在没有相关深入了解前,对此类问题是很难获取到准确的信息,从以上问题的探索过程中,我们需要了解一些关于事件的定义和更多知识以便于后期对此类问题的分析与深入
-
浏览器人性化设计
-
浏览器事件继承概念,为了便于和定义制定者保持一致,使用英文进行罗列
- Sync / Async => 是同步还是异步 ?
- Bubbles => 能否冒泡
- Trusted
- Cancelable
- Composed
- etc.
- 浏览器实现厂商对w3c的继承性和扩展性,例如对 activation behavior 的定义 activation-behavior
- interactive 定义
以上只是目前笔者能够想到的部分问题,基于一些我们可以做出合理的推测,假如为了避免浏览器对人注意力的distractions, 是否能静默播放? 也就是volume为0的情况下进行播放,我想上面的信息应该足够屏幕前的你做出初步的判断,剩下的就是去验证吧.
联想场景
- 架构师对封面图的设计,对首帧图片的存储是否必要,对象存储大部分能够提供任意帧图片的获取方式,如果使用的服务是自己的就需要知道一些浏览器的限制
- 如果产品经理要求在页面刚进入时候便弹出文件选择框是否能实现
- 用户滑动到某一个位置的时候自动下载一个 Trojan.exe 到文件系统能实现吗
- 浏览器的沙箱定义
如何决策
ALL DEPENDS ON YOU !