AudioContext创建播放器

1.现在很多场景下我们需要直接调用js来创建播放器,这个时候就会遇到一些兼容性问题。在edge、火狐等浏览器中直接用new window.Audio()会播放不了,所以针对edge、火狐等浏览器就可以使用AudioContext来创建播放器。

2.封装一个简单的AudioContext播放器

export class Audio {
  _buffers = []
  _context
  _gainNode
  _sourceNode
  _url
  _state 
  start = async () => {
    try {
      await this._getAllBuffer()
      this._createAudioEdge().then(() => {
        console.log('获取了audio')
      }).catch(e => console.log('audio', e))
    } catch (e) {
      console.log('start Exception', e)
    }
  }
  _createAudioEdge = async () => {
    this._context = new AudioContext()
    const audioBuffer = await this._decodeAudioData(this._getMergeBuffer())
    let { source, gainNode } = this._createSourceNode(audioBuffer)
    this._sourceNode = source
    this._gainNode = gainNode
  }
  // 将回调函数转化为promise
  _decodeAudioData (arrayBuffer) {
    return new Promise((resolve, reject) => {
      this._context.decodeAudioData(arrayBuffer, audioData => {
        resolve(audioData)
      })
    })
  }
  // 得到合并后的buffer
  _getMergeBuffer () {
    let mergeBuffer
    for (let i = 0; i < this._buffers.length; i++) {
      let tempBuffer = this._buffers[i]
      if (mergeBuffer) { mergeBuffer = this._concatBuffer(mergeBuffer, tempBuffer) } else { mergeBuffer = tempBuffer }
    }
    return mergeBuffer
  }
  // 连接两个buffer
  _concatBuffer = (buffer1, buffer2) => {
    let tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength)
    let buff1 = new Uint8Array(buffer1)
    let buff2 = new Uint8Array(buffer2)
    tmp.set(buff1, 0)
    tmp.set(buff2, buffer1.byteLength)
    return tmp.buffer
  }
  // 自己获取所有buff,根据自己的场景来获取自己的buff
  _getAllBuffer = async () => {
    return new Promise((resolve, reject) => {
      getAllBuffer(this._url).then(async res => {
        this._buffers = []
        this._buffers.push(res)
        resolve()
      }).catch(e => reject(e))
    })
  }
}

3.创建歌曲的状态值
// Audio的状态

export const AudioState = {
  suspended: 'suspended',
  running: 'running',
  closed: 'closed',
  loading: 'loading',
  error: 'error'
}

4.播放器的一些操作

  /**
   * public method
   * 播放器逻辑方法
   * @returns {Promise<void>}
   */
  play = () => {
    this.setAudioState(AudioState.running)
    this._nativeAudio.play()
  }
  /**
   * public method
   * 继续播放
   */
  resume () {
    this.setAudioState(AudioState.running)
    if (this._context) {
      this._context.resume()
    }
  }
  /**
   * public method
   * 暂停播放
   */
  pause () {
    this.setAudioState(AudioState.suspended)
    if (this._context) {
      this._context.suspend()
    }
  }
  /**
   * public method
   * 关闭
   */
  close () {
    if (!this._context) return
    this.setAudioState(AudioState.closed)
    this.pause()
    this._context.close()
    this._context = null
  }
  /**
   * public method
   * 歌曲状态设置
   */
  setAudioState (val) {
    let playStatus = -1 // -1未定义audio,0暂停,1播放,2缓冲, 3播放完毕
    switch (val) {
      case AudioState.suspended:
        playStatus = 0
        break
      case AudioState.running:
        playStatus = 1
        break
      case AudioState.loading:
        playStatus = 2
        break
      case AudioState.closed:
        playStatus = 3
        break
      case AudioState.error:
        playStatus = 4
        break
      default:
        playStatus = -1
        break
    }
    this._state = playStatus
  }
  get status () {
    return this._state
  }

一个简单的AudioContext播放器的封装,希望能帮助到大家,如有优化或者问题可以私聊我下。谢谢。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容