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:

  1. HAVE_NOTHING(数字值为0):没有获取到媒体的任何信息,当前播放位置没有可播放数据。
  2. HAVE_METADATA(数字值为1):已经获取到足够的媒体数据,但是当前播放位置没有有效的媒体数据(也就是说,获取到的媒体数据无效,不能播放)。
  3. HAVE_CURRENT_DATA(数字值为2):当前播放位置已经有数据可以播放,但没有获致到可以让播放器前进的数据。当媒体为视频时,意思是当前帖的数据已获取,但没有获取到下一帧的数据,或者当前帧已经是播放的最重一帧。
  4. 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 的兼容性问题还是挺大的。
我们需要自己开发一个播放器时,需要考虑到以下几点:

  1. 加载中
  2. 播放进度
  3. 播放状态
  4. 结束状态
  5. 错误处理

    7.1 加载中

    通常 canplay canplaythrough 标志缓冲完成可以播放,他们是比较好的结束加载中状态的时机。但是现在浏览器特别是移动端浏览器,对这它们的兼容性不是很好。主要是iOS 端微信微博几乎是把 preload 属性给干掉了,不使用特殊手法,不会在用户没有任何操作的情况下触发 canplay canplaythrough。
    对于微信,可以加载微信的 js-sdk。在 wx.ready 里触发自动播放来解决这个问题。
  1. // 自动播放 微信 iOS 环境,不加此代码,则readyState状态一直为 1, 不受 preload 控制
  2. wx.config({
  3. // 配置信息, 即使不正确也能使用 wx.ready
  4. debug: false,
  5. appId: '',
  6. timestamp: 1,
  7. nonceStr: '',
  8. signature: '',
  9. jsApiList: [],
  10. })
  11. wx.ready(function() {
  12. audioEle.play()
  13. audioEle.pause()
  14. })

safari 浏览器设置 preload: auto 也不会触发 canplay canplaythrough, 可以调用下 audio 的 load 方法来 hack。

所以不建议在页面加载时就显示加载中的动画,防止有些特殊的 app 和浏览器无法在用户有操作前给到 canplay。可以在页面做好 hack,提前加载媒体信息,但是等到用户有操作后(比如点击播放按钮)再显示加载中。

另外加载中需要显示媒体时长,大部分手机在 durationchange 和 loadedmetadata 时都能获得正确的 duration 属性,但是测试时发现小米有一款手机在使用原生浏览器时,必须在实际播放后才能拿到正确的 duration,其他情况下都返回 0。这种情况可以在 canplay 后手动调用 play 来 hack。

  1. // hack 小米原生浏览器第一次获取 duratiuon 为 0, 必须 play 后才能获取正确的 duration
  2. audio.play()
  3. audio.pause()

另外需要注意一点,canplay canplaythrough 在 chrome 和大部分安卓上,设置 currentTime 后也会触发,做好兼容。IOS 加载资源,服务器使用 HTTP 响应头 Accept-Ranges,Accept-Ranges: bytes。

video标签在iPhone手机上不能播放?万能的知乎大神请指引我,实在没办法了

7.2 播放进度

可以使用 timeupdate 事件,理论上在播放进度改变时这个事件就会触发,这个时候改变进度条就好了。
但是有些浏览器在 canplay 前设置 currentTime 不会触发 timeupdate,QQ 浏览器在有些手机上 canplay 后设置 currentTime 也不会触发,必须要播放过才行。所以如果需要做到在播放前就可以设置播放进度,需要考虑自己改变下进度条样式。

7.3 播放状态

监听 playing 和 pause 事件即可。
注意一点:pc chrome 上,设置 currentTime 会触发 palying pause。用户拖动进度条时,频繁修改 currentTime,按钮可能不能地在播放和暂停间切换,需要做好处理。

7.4 结束状态

ended 兼容性良好,目前没遇到什么坑。

7.5 错误处理

ended 兼容性良好,目前也没遇到什么坑。