问题描述
我一直在开发音乐应用程序,今天终于到了开始尝试将音乐播放到其中的地步。
作为我的环境设置的概述,我将音乐文件存储为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 (将#修改为@)