NuxtJS2实现无卡顿高性能的音频播放

本文阅读 4 分钟
广告

之前项目的时候,遇到一个这样的需求,一是要求一个网页有背景音乐播放,并且切换页面的时候不中断,二是每个按钮点击都需要有音效。乍一看很简单,只需要在页面上创建audio标签,然后在js里调用播放。
但是实际上,当我引入了背景音乐,鼠标音效之后,网页在进来的瞬间直接卡到起飞,直接导致浏览器未响应,就算音频加载完成了,也会导致用户在进行每个操作的时候都会异常卡顿,所以,就必须找到新的方法来解决这个问题。
nuxtJS

具体原因

因为在音频标签在引入后,浏览器加载时,会直接同时解析所有的音频,导致浏览器卡顿。所以需要将所有音频预加载,先存储到内存中。

代码案例

1.对于背景音乐,可以使用预加载办法,提前存储到内存中,避免加载和解析导致的卡顿,具体代码如下。

import Vue from 'vue'
//加载背景音乐
const audioUrls = ['/mp3/home-bg.mp3', '/mp3/start-bg.mp3']
const audioMap = {}
for (const url of audioUrls) {
  const audio = new Audio()
  audio.src = url
  audio.load()
  audio.onloadeddata = () => {
    console.log(`音频 ${url} 加载完成`)
  }
  audioMap[url] = audio
}
Vue.prototype.$audioMap = audioMap;

在项目的plugins文件夹中创建bgAudio.js,放入上述代码,再进入项目的nuxt.config.js,找到plugins: []部分,加入如下代码:

 { src: '@/plugins/bgAudio.js', mode: 'client' },

调用背景音乐时,代码如下:

this.audio = that.$audioMap['/mp3/start-bg.mp3'];//定义音频对象
this.audio.loop = true; //设置循环播放
this.$audioMap['/mp3/home-bg.mp3'].pause() //暂停播放
this.$audioMap['/mp3/home-bg.mp3'].currentTime = 0 //从0秒开始播放
//其它的控制和一般的audio操作完全一致

这样,由于背景音乐直接js预加载到内存,需要的时候调用,就省略的浏览器加载解析的过程,就解决了一半的卡顿问题。然后,还可以用以下方法判断图片是否加载完成。

var audio1State =  this.$audioMap['/mp3/home-bg.mp3'].readyState;
//4就是加载完成,其它的百度查一下吧。

2.对于按钮点击音效,因为按钮操作会非常多,而且可能不同按钮音效不同,所以不能写死去预加载,而是灵活的进行调用。plugins文件夹中创建btnAudio.js,代码如下:

class AudioPlayer {
  constructor() {
    this.audioContext = null
    this.gainNode = null
    this.isPlaying = false
    this.currentSource = null
    this.audioBufferMap = {}
    this.initAudio()
  }

  initAudio() {
    //兼容iPhone旧版本
    if ('AudioContext' in window || 'webkitAudioContext' in window) {
      this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
    } else {
      console.error('Web Audio API not supported');
    }
    this.gainNode = this.audioContext.createGain()
    this.gainNode.connect(this.audioContext.destination)
  }

  play(src, loop = false) {
    if (this.isPlaying) {
      this.stop()
    }

    if (this.audioBufferMap[src]) {
      this.playBuffer(this.audioBufferMap[src], loop)
    } else {
      let request = new XMLHttpRequest()
      request.open('GET', src, true)
      request.responseType = 'arraybuffer'

      request.onload = () => {
        this.audioContext.decodeAudioData(request.response, buffer => {
          this.audioBufferMap[src] = buffer
          this.playBuffer(buffer, loop)
        }, () => {
          console.error('decodeAudioData error')
        })
      }

      request.send()
    }
  }

  preload(src) {
    if (!this.audioBufferMap[src]) {
      let request = new XMLHttpRequest()
      request.open('GET', src, true)
      request.responseType = 'arraybuffer'

      request.onload = () => {
        this.audioContext.decodeAudioData(request.response, buffer => {
          this.audioBufferMap[src] = buffer
        }, () => {
          console.error('decodeAudioData error')
        })
      }

      request.send()
    }
  }

  playBuffer(buffer, loop) {
    this.currentSource = this.audioContext.createBufferSource()
    this.currentSource.buffer = buffer
    this.currentSource.loop = loop
    this.currentSource.connect(this.gainNode)
    this.currentSource.start(0)
    this.isPlaying = true
  }

  pause() {
    if (this.isPlaying && this.currentSource) {
      this.currentSource.stop(0)
      this.isPlaying = false
    }
  }

  stop() {
    if (this.isPlaying && this.currentSource) {
      this.currentSource.stop(0)
      this.isPlaying = false
    }
  }
}

const audioPlayer = new AudioPlayer()

export default ({ app }, inject) => {
  inject('audio', audioPlayer)
}

再进入项目的nuxt.config.js,找到plugins: []部分,加入如下代码:

{ src: '@/plugins/btnAudio.js', ssr: false },

调用按钮音效时,代码如下:

this.$audio.play('/mp3/click.wav')

也可以提前预加载,用如下代码:

this.$audio.preload('/mp3/click.wav')

这样,第一次点击按钮时,则加载音乐到存储,之后每次调用同样的文件时直接调用缓存。这样就解决了性能问题,

最后

NuxtJS2+VUE2配合起来,感觉非常适合开发桌面客户端,不过具体还在研究中。对于NuxtJS3,生态支持和文档都太少了,还是过段时间研究把。

本文来自投稿,不代表本站立场,如若转载,请注明出处:https://www.ruletree.club/archives/3420/
关于app中文章封面图不显示的问题及解决方法
« 上一篇 02-16
NuxtJS2图片加载优化,预缓存和调用
下一篇 » 06-14
广告

发表评论

V注册会员 L评论等级
R1 条回复
  1. 马化腾VLv.1 说道:
    2023-07-22     Android /    Chrome

没有更多评论了

作者信息

热门文章

标签TAG

热评文章