https://www.yuque.com/chenshier/chuyi/cl0x98 多媒体(video和audio)
1. HTML常用属性
类型 | 说明 | |
---|---|---|
autoplay | boolean | 如果出现该属性,则音频在就绪后马上播放。 为了防止网页在用户没有准备的情况下发出奇怪的声音,大多数浏览器都会禁止这个功能。包括 chrome。 |
loop | boolean | 是否循环播放。 |
muted | boolean | 是否静音。 |
controls | boolean | 是否显示播放器控件。需要注意的是不同浏览器 UI 不一致。 |
preload | string | none: 点击播放前不加载任何信息 metadata: 网页加载时加载音频 meta 信息,如时长等 auto: 网页加载时下载整个音频,不同浏览器表现不一致 |
src | string | 音频地址 |
2. 只读属性
说明 | |
---|---|
duration | 音频总时长,以秒为单位。如果无法获取时长,则返回NaN |
paused | 是否处在暂停状态。未开始播放,播放时点击暂停都返回 true |
ended | 媒体文件是否播放完毕 |
buffered | 返回当前已缓冲的时间段 |
readyState | 获取当前媒体文件的加载程度 |
error | 错误信息 |
readyState:
- HAVE_NOTHING(数字值为0):没有获取到媒体的任何信息,当前播放位置没有可播放数据。
- HAVE_METADATA(数字值为1):已经获取到足够的媒体数据,但是当前播放位置没有有效的媒体数据(也就是说,获取到的媒体数据无效,不能播放)。
- HAVE_CURRENT_DATA(数字值为2):当前播放位置已经有数据可以播放,但没有获致到可以让播放器前进的数据。当媒体为视频时,意思是当前帖的数据已获取,但没有获取到下一帧的数据,或者当前帧已经是播放的最重一帧。
- HAVE_FUTURE_DATA(数字值为3):当前播放位置已经有数据可以播放,而且也获取到了可以让播放器前进的数据。当媒体为视频时,意思是当前帧的数据已获取,而且也获取到了下刺目贩数据,当前帧是播放的最后一帧时,readyState属性不可能为HAVE_FUTURE_DTAT。 HAVE_ENOUGH)DATA(数字值为4):当前播放位置已经有数据可以播放,同时也获取到了可以让播放器前进的数据,而且浏览器确认媒体以某一种速度进行加载,可以保证有足够的后续数据进行播放。
3. 可读写属性
类型 | 说明 | |
---|---|---|
autoplay | 见 HTML 常用属性 | 见 HTML 常用属性 |
loop | 见 HTML 常用属性 | 见 HTML 常用属性 |
currentTime | Number | 指定播放进度,单位为秒 |
controls | 见 HTML 常用属性 | 见 HTML 常用属性 |
volume | Number | 设置音量 |
muted | 见 HTML 常用属性 | 见 HTML 常用属性 |
playbackRate | Number | 设置播放速度 |
4. 常用事件
加载音频时按顺序触发下面的事件
说明 | |
---|---|
loadstart | 开始加载音频时触发 |
durationchange | duation 属性发送变化时触发 |
loadedmetadata | 媒体文件元数据加载完毕时触发 |
loadeddata | 媒体文件第一帧加载完毕时触发 |
progress | 下载媒体文件时触发 |
canplay | 浏览器准备好播放时触发,readyState 2 |
canplaythrough | 浏览器认为可不缓冲播放时触发,readyState 3 |
还有如下常用事件:
说明 | |
---|---|
playing | 开始播放时触发,包括第一次播放、暂停后播放、结束后重新播放 |
pause | 播放暂停时触发 |
ended | 播放结束时触发 |
error | 发生错误时触发 |
timeupdate | 播放进度 currentTime 改变时触发 |
其他未说明的可见 https://www.kancloud.cn/dennis/tgjavascript/241833
5. 常用方法
说明 | |
---|---|
canPlayType | 测试浏览器是否支持指定的媒体类型。如果它不能播放该类型的媒体文件,将返回一个空的字符串;反之,它会返回一个字符串:“maybe”或“probably”。 |
play | 开始播放 |
pause | 暂停播放 |
load | 重新加载 src 指定的资源 |
6. 兼容性测试
6.1 PC
机型 MacBook Pro (Retina, 13-inch, Early 2015)
系统 MacOS Mojave 10.14.5
Chrome 75.0.3770.100 | Safari 12.1.1 | |
---|---|---|
currentTime | 1. canplay 前设置 : 浏览器会记住设置的值,但是不会触发 timeupdate。点击播放后会从指定值开始播放 2. canplay 后设置: 触发 timeupdate、canplay、canplaythrough、progress、playing、pause 保持原先的播放状态 |
1. canplay 前设置:完全无效 2. canplay 后设置:timeupdate、pregress,保持原先播放状态 |
preload | 1. none: loadstart 2. metadata: loadstart、durationchange、loadedmetadata、canplay、canplaythrough 3. auto: loadstart、durationchange、loadedmetadata、canplay、canplaythrough、progress |
1. none:loadstart、pregress(只会下载到 readyState 0) 2. metadata: oadstart、durationchange、loadedmetadata、progress(readyState 1) 3. auto: loadstart、durationchange、loadedmetadata、canplay、canplaythrough、progress |
autoplay | true: 不会自动播放, 效果类似 preload: metadata | true: 不会自动播放, 效果类似 preload:none |
canplay | canplay 后每次设置 currentTime 后都会触发 | 只有 preload 为 auto,初次加载触发,设置 currentTime 不触发 |
canplaythrough | 同上 | 同上 |
6.2 iOS
机型 iPhone 8Plus
系统 iOS 12.3.2
safari | 微信7.0.5内置 Webview | QQ 8.0.8.458 内置 Webview | 微博 9.7.1 内置 Webview | QQ 浏览器 9.5.1.4171 | UC 浏览器 12.5.4.1194 | |
---|---|---|---|---|---|---|
currentTime | 1. canplay 前设置 :无效 2. canplay 后设置: 触发 timeupdate、progress, 保持原先的播放状态 3. 第一次触摸屏幕设置 currentTime 或者调用 play,触发 canplay、canplaythrough、progress |
1. canplay 前设置 : 无效 2. canplay 后设置:同 safari 3. 第一次触摸屏幕设置 currentTime:无效 4. 第一次触摸屏幕调用 play:loadstart、durationchange、loadedmetadata、canplay、canplaythrough、progress、timeupdate |
同 safari | 同微信 | 同 safari | 同 safari |
preload | 1. none: loadstart、progress(readyState 0) 2. metadata: loadstart、durationchange、loadedmetadata、progress(readyState 1) 3. auto: 同 metadata |
1. none: 无效果 2. metadata:无效果 3. auto: 无效果 |
1. none: 同 safari 2. metadata:同 safari 3. auto: 同 safari |
1. none:无效果 2. metadata: 无效果 3. auto: 无效果 |
1. none:同 safari 2. metadata: 同 safari 3. auto: 同 safari |
1. none:同 safari 2. metadata:同 safari 3. auto: 同 safari |
autoplay | true: 不会自动播放, 效果类似 preload: metadata | true: 不会自动播放,未触发任何audio事件 | 同 safari | 同微信 | 同 safari | 同 safari |
canplay canplaythrough | 1. 触摸屏幕后调用 play 或者设置 currentTime 触发 2. 调用 autio 标签的 load 方法可以触发 |
1. 触摸屏幕后调用 play 触发 2. 集成微信 js-sdk 在 wx.ready 后调用 play 可以触发,也可以自动播放 |
同 safari | 1. 触摸屏幕后调用 play 触发 |
同 safari | 同 safari |
6.3 Android
机型:Pixel XL
系统:Android 9.0.0
chrome 66.0.3359.158 | 微信7.0.3内置 Webview | QQ 7.9.2.3845 内置 Webview | 微博 9.7.2.1 内置 Webview | QQ 浏览器 8.9.3.4562 | UC 浏览器 12.5.5.1035 | |
---|---|---|---|---|---|---|
currentTime | - canplay 前设置 : 浏览器会记住设置的值,但是不会触发 timeupdate。点击播放后会从指定值开始播放 - canplay 后设置: 触发 timeupdate、canplay、canplaythrough、progress、playing 保持原先的播放状态 |
同 chrome | 同 chrome | 同 chrome | canplay 前设置 : 浏览器会记住设置的值,但是不会触发 timeupdate。点击播放后会从指定值开始播放 canplay 后但尚未播放过设置: 同 canplay 前。 canplay 后且播放过设置:timeupdate、canplay、canplaythrough、progress、playing |
无 canplay 前状态 canplay 后设置同 chrome |
preload | 1. none: loadstart 2. metadata: loadstart、durationchange、loadedmetadata、canplay、canplaythrough、progress 3. auto: 同上 |
1. none: 同chrome 2. metadata:同 chrome 3. auto: 同chrome |
1. none: 同chrome 2. metadata:同chrome 3. auto: 同 chrome |
1. none:同chrome 2. metadata: 同chrome 3. auto:同chrome |
1. none:同chrome 2. metadata:同chrome 3. auto:同 chrome |
1. none:loadstart、durationchange、loadedmetadata、canplay、canplaythrough、progress 2. metadata:同 chrome 3. auto: 同 chrome |
autoplay | true: 无效 | true:可自动播放 | true:可自动播放 | true: 无效 | true:可自动播放 | true: 无法自动播放,当与preload: auto 共存时会重复触发preload: auto 对应的事件,但是得到的 duration 是错误的 |
canplay canplaythrough | 1. preload: metadata,auto 触发 2. 设置 currentTime 触发 |
同 chrome | 同 chrome | 同 chrome | 同 chrome | 同 chrome |
机型华为 P30
系统 Android 9 EMUI 9.1.0
由于测到一半测试机被测试拿回去了,所以只有一部分数据。。。。
系统自带浏览器 9.1.1.306 | 微信7.0.5内置 Webview | QQ 8.0.0.4000 内置 Webview | 微博 9.4.3 内置 Webview | QQ 浏览器 9.4.15009 | UC 浏览器 12.0.2.989 | |
---|---|---|---|---|---|---|
preload | 1. none: loadstart 2. metadata: loadstart、durationchange、loadedmetadata、canplay、canplaythrough 3. auto: loadstart、durationchange、loadedmetadata、canplay、canplaythrough、progress(readyState 4) |
1. none: 同系统自带浏览器 2. metadata: 同系统自带浏览器 3. auto: 同系统自带浏览器 |
1. none: 同系统自带浏览器 2. metadata: loadstart、durationchange、loadedmetadata、canplay、canplaythrough、pregress(readyState 0) 3. auto: 同系统自带浏览器 |
1. none:同系统自带浏览器 2. metadata: 同系统自带浏览器 3. auto:同系统自带浏览器 |
1. none:同系统自带浏览器 2. metadata:同系统自带浏览器 3. auto:loadstart、durationchange、loadedmetadata、canplay、canplaythrough |
1. none:loadstart、progress(readyState 0) 2. metadata: 同 QQ 内置 Webview 3. auto: loadstart、durationchange、loadedmetadata、canplay、canplaythrough、progress(readyState 0) |
autoplay | true: 可自动播放 | true: 同系统自带浏览器 | true:同系统自带浏览器 | true: 无效 | true: 同系统自带浏览器 | true: 无法自动播放,当与preload: auto 共存时会重复触发preload: auto 对应的事件,但是得到的 duration 是错误的 |
7. 总结
目前 audio 的兼容性问题还是挺大的。
我们需要自己开发一个播放器时,需要考虑到以下几点:
- 加载中
- 播放进度
- 播放状态
- 结束状态
- 错误处理
7.1 加载中
通常 canplay canplaythrough 标志缓冲完成可以播放,他们是比较好的结束加载中状态的时机。但是现在浏览器特别是移动端浏览器,对这它们的兼容性不是很好。主要是iOS 端微信微博几乎是把 preload 属性给干掉了,不使用特殊手法,不会在用户没有任何操作的情况下触发 canplay canplaythrough。
对于微信,可以加载微信的 js-sdk。在 wx.ready 里触发自动播放来解决这个问题。
// 自动播放 微信 iOS 环境,不加此代码,则readyState状态一直为 1, 不受 preload 控制
wx.config({
// 配置信息, 即使不正确也能使用 wx.ready
debug: false,
appId: '',
timestamp: 1,
nonceStr: '',
signature: '',
jsApiList: [],
})
wx.ready(function() {
audioEle.play()
audioEle.pause()
})
safari 浏览器设置 preload: auto 也不会触发 canplay canplaythrough, 可以调用下 audio 的 load 方法来 hack。
所以不建议在页面加载时就显示加载中的动画,防止有些特殊的 app 和浏览器无法在用户有操作前给到 canplay。可以在页面做好 hack,提前加载媒体信息,但是等到用户有操作后(比如点击播放按钮)再显示加载中。
另外加载中需要显示媒体时长,大部分手机在 durationchange 和 loadedmetadata 时都能获得正确的 duration 属性,但是测试时发现小米有一款手机在使用原生浏览器时,必须在实际播放后才能拿到正确的 duration,其他情况下都返回 0。这种情况可以在 canplay 后手动调用 play 来 hack。
// hack 小米原生浏览器第一次获取 duratiuon 为 0, 必须 play 后才能获取正确的 duration
audio.play()
audio.pause()
另外需要注意一点,canplay canplaythrough 在 chrome 和大部分安卓上,设置 currentTime 后也会触发,做好兼容。IOS 加载资源,服务器使用 HTTP 响应头 Accept-Ranges
,Accept-Ranges: bytes。
7.2 播放进度
可以使用 timeupdate 事件,理论上在播放进度改变时这个事件就会触发,这个时候改变进度条就好了。
但是有些浏览器在 canplay 前设置 currentTime 不会触发 timeupdate,QQ 浏览器在有些手机上 canplay 后设置 currentTime 也不会触发,必须要播放过才行。所以如果需要做到在播放前就可以设置播放进度,需要考虑自己改变下进度条样式。
7.3 播放状态
监听 playing 和 pause 事件即可。
注意一点:pc chrome 上,设置 currentTime 会触发 palying pause。用户拖动进度条时,频繁修改 currentTime,按钮可能不能地在播放和暂停间切换,需要做好处理。
7.4 结束状态
7.5 错误处理
ended 兼容性良好,目前也没遇到什么坑。