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):已经获取到足够的媒体数据,但是当前播放位置没有有效的媒体数据(也就是说,获取到的媒体数据无效,不能播放)。  
  1. HAVE_CURRENT_DATA(数字值为2):当前播放位置已经有数据可以播放,但没有获致到可以让播放器前进的数据。当媒体为视频时,意思是当前帖的数据已获取,但没有获取到下一帧的数据,或者当前帧已经是播放的最重一帧。  
  1. 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 里触发自动播放来解决这个问题。


// 自动播放  微信 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 后也会触发,做好兼容。


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 兼容性良好,目前也没遇到什么坑。



8. 参考资料

  1. 多媒体(video和audio)