使用Web Audio API时的播放会在每个块的开头跳过

问题描述

我一直在开发音乐应用程序,今天终于到了开始尝试将音乐播放到其中的地步。

作为我的环境设置的概述,我将音乐文件存储为MP3,并已使用GridFS将其上传到MongoDB数据库中。然后,我使用socket.io服务器从MongoDB数据库下载块,并将它们作为单个发射发送到前端,在前端由Web Audio API处理并计划播放。

当他们演奏时,它们的顺序都正确,但是每次(似乎在块之间)都有一个很小的毛刺或跳到相同的位置,这似乎是我无法摆脱的。据我所知,它们都是紧挨着安排的,因此我找不到它们之间应该存在任何间隙或重叠的原因。任何帮助,将不胜感激。这是代码:

套接字路由

socket.on('stream-audio',() => {
  db.client.db("dev").collection('music.files').findOne({"metadata.songId": "3"}).then((result) =>{
      const bucket = new GridFSBucket(db.client.db("dev"),{
        bucketName: "music"
      });
      bucket.openDownloadStream(result._id).on('data',(chunk) => {
      socket.emit('audio-chunk',chunk)
    });
  });
});

前端

//These variable are declared as object variables,hence all of the "this" keywords
context: new (window.AudioContext || window.webkitAudioContext)(),freeTime: null,numChunks: 0,chunkTracker: [],...

this.socket.on('audio-chunk',(chunk) => {
      //Keeping track of chunk decoding status so that they don't get scheduled out of order
      const chunkId = this.numChunks
      this.chunkTracker.push({
        id: chunkId,complete: false,});
      this.numChunks += 1;

      //Callback to the decodeAudioData function
      const decodeCallback = (buffer) => {
        var shouldExecute = false;
        const trackIndex = this.chunkTracker.map((e) => e.id).indexOf(chunkId);

        //Checking if either it's the first chunk or the previous chunk has completed
        if(trackIndex !== 0){
          const prevChunk = this.chunkTracker.filter((e) => e.id === (chunkId-1))
          if (prevChunk[0].complete) {
            shouldExecute = true;
          }
        } else {
          shouldExecute = true;
        }

        //THIS IS THE ACTUAL WEB AUDIO API STUFF
        if (shouldExecute) {
          if (this.freeTime === null) {
            this.freeTime = this.context.currentTime
          }
          const source = this.context.createBufferSource();
          source.buffer = buffer
          source.connect(this.context.destination)
          if (this.context.currentTime >= this.freeTime){
            source.start()
            this.freeTime = this.context.currentTime + buffer.duration
          } else {
            source.start(this.freeTime)
            this.freeTime += buffer.duration
          }
          //Update the tracker of the chunks that this one is complete
          this.chunkTracker[trackIndex] = {id: chunkId,complete: true}
        } else {
          //If the previous chunk hasn't processed yet,check again in 50ms
          setTimeout((passBuffer) => {
            decodeCallback(passBuffer)
          },50,buffer);
        }
      }
      decodeCallback.bind(this);
      
      this.context.decodeAudioData(chunk,decodeCallback);
    });

任何帮助将不胜感激,谢谢!

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)