使用ArrayBuffer录制MP3

3
我在Stackoverflow上尝试了很多方法,但是都无法实现目标。于是我尝试使用nodejs从树莓派录制音频(1)。然后将这个流通过websocket服务器传输(我没有放出这段代码,因为它只是一个重定向)。最后,vuejs中的websocket监听该流。接着,我想要将该流录制为mp3格式(2),但是有噪声或者没有任何声音。 1 - 树莓派:
ai = new audio.AudioIO({
        inOptions: {
          channelCount: 1,
          sampleFormat: audio.SampleFormat16Bit,
          sampleRate: 44100,
          deviceId: 6, // Use -1 or omit the deviceId to select the default device
          closeOnError: true // Close the stream if an audio error is detected, if set false then just log the error
        }
      });

      ai.on('data', buf => {
      
      clientAudioWebsocket.send(buf)
      }
      );
      
     
      ai.start();  

2- Vuejs 的第二部分

  • Socket :

     this.dataBuffer = []
    
       var self = this
    
       var connectionToLocalServer = new WebSocket("ws://"+ip  +":4444")
       connectionToLocalServer.binaryType = "arraybuffer"
    
        connectionToLocalServer.onmessage = function(event) {
            self.dataBuffer.push(event.data);
    
        }
        connectionToLocalServer.onopen = function(event) {
    
    
      }
    
  • part arraybuffer to mp3

      concatArrayBuffers (bufs) {
                              var offset = 0;
                              var bytes = 0;
                              var bufs2=bufs.map(function(buf,total){
                                  bytes += buf.byteLength;
                                  return buf;
                              });
                              var buffer = new ArrayBuffer(bytes);
                              var store = new Uint8Array(buffer);
                              bufs2.forEach(function(buf){
                                  store.set(new Uint8Array(buf.buffer||buf,buf.byteOffset),offset);
                                  offset += buf.byteLength;
                              });
                              return buffer }
    
    
    
              this.tmpResult = this.concatArrayBuffers(this.dataBuffer);
    
              var mp3Data = [];
    
              var mp3encoder = new lamejs.Mp3Encoder(1, 44100, 128);
    
              var mp3Tmp = mp3encoder.encodeBuffer(this.tmpResult, 0, Math.floor(this.tmpResult.byteLength / 2)); 
            //Push encode buffer to mp3Data variable
              mp3Data.push(mp3Tmp);
    
              // Get end part of mp3
              mp3Tmp = mp3encoder.flush();
    
              // Write last data to the output data, too
              // mp3Data contains now the complete mp3Data
              mp3Data.push(mp3Tmp);
    

我不明白为什么我的ArrayBuffer有16384大小的缓冲区。

我非常乐意接受任何解决方案,但我不想在服务器端处理它。

谢谢。

关于为什么我有一个大小为16384的ArrayBuffer,最初的两个字节值是什么?array[0]=255array[0]=251吗?如果是的话,那么你的arrayBuffer可能已经是MP3格式了,这就可以解释为什么Lame编码器输出噪音。 - VC.One
@VC.One。感谢您的回答,我明天会检查一下。但我不认为这是问题所在。因为当我从服务器arraybuffer录制到wav文件时没有问题。我认为问题可能出现在连接arrayBuffers和之后如何使用lamejs方面。但我会检查。 - ande
2个回答

2

我找到了解决方法,原因是我没有创建一个Int16Array :-( (有时候最好出去走一小时,之后你就能找到解决方法)

解决方法如下:

let tmpResult = this.concatArrayBuffers(this.dataBuffer)
     
var samples = new Int16Array(tmpResult);
var buffer = [];
var mp3enc = new lamejs.Mp3Encoder(1, 44100, 128);
var remaining = samples.length;
var maxSamples = 1152;
for (var i = 0; remaining >= maxSamples; i += maxSamples) {
     var mono = samples.subarray(i, i + maxSamples);
     var mp3buf = mp3enc.encodeBuffer(mono);
     if (mp3buf.length > 0) {
         buffer.push(new Int8Array(mp3buf));
        }
        remaining -= maxSamples;
}
var d = mp3enc.flush();
if(d.length > 0){
 buffer.push(new Int8Array(d));
}

console.log('done encoding, size=', buffer.length);
var blob = new Blob(buffer, {type: 'audio/mp3'});

0

您可以在此处导航-> https://github.com/charlielee/mp3-stream-recorder 我推荐这个。 迟早我会制作一个漂亮的 GUI Web 应用程序来完成这个工作,而不是依赖于 cronjob。 用法

在终端窗口或 cronjob 中运行以下内容:

$ node index.js -s "http://firewall.pulsradio.com" -d 20000 -o "./shows"

注意:如果将其作为 cronjob 运行,则 node 和 index.js 需要是它们各自位置的绝对路径。

参数

-s The URL of the stream to record (default http://firewall.pulsradio.com)
-d The duration in milliseconds to record for (default 5000)
-o The output directory of the file (default ./shows)

IFTTT 支持

还可以提供以下参数,以便在每次录制完成时触发 IFTTT Webhook 应用程序。

--ifttt_event The Event Name entered on the Webhook applet
--ifttt_key The user's IFTTT Webhooks key

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接