JavaScript: Как разбить аудио-блоб на 1-секундные куски и экспортировать в файлы WAV с помощью Recorder.js? - PullRequest
0 голосов
/ 18 марта 2019

Я хочу записать голос, автоматически разделить записанный голос (или аудиоблок) на фрагменты длительностью 1 секунда, экспортировать каждый фрагмент в файл wav и отправить его на сервер. Это должно происходить асинхронно, пока пользователь говорит.

В настоящее время я использую следующую библиотеку Recorder.js для выполнения вышеуказанных задач. https://cdn.rawgit.com/mattdiamond/Recorderjs/08e7abd9/dist/recorder.js

Моя проблема в том, что со временем размер файла blob / wave увеличивается. Я думаю, это потому, что данные накапливаются и увеличивают размер чанка. Так что со временем я на самом деле отправляю не последовательные порции в 1 секунду, а накопленные порции.

Я не могу понять, где в моем коде возникла эта проблема. Может быть, это происходит внутри библиотеки Recorder.js. Если кто-то использовал устройство записи js или любой другой метод JavaScript для аналогичных задач, оцените, можете ли вы пройти этот код и сообщить мне, где он ломается.

Это мой код JS

var gumStream; // Stream from getUserMedia()
var rec; // Recorder.js object
var input; // MediaStreamAudioSourceNode we'll be recording
var recordingNotStopped; // User pressed record button and keep talking, still not stop button pressed
const trackLengthInMS = 1000; // Length of audio chunk in miliseconds
const maxNumOfSecs = 1000; // Number of mili seconds we support per recording (1 second)


// Shim for AudioContext when it's not available. 
var AudioContext = window.AudioContext || window.webkitAudioContext;
var audioContext //audio context to help us record

var recordButton = document.getElementById("recordButton");
var stopButton = document.getElementById("stopButton");

//Event handlers for above 2 buttons
recordButton.addEventListener("click", startRecording);
stopButton.addEventListener("click", stopRecording);

//Asynchronous function to stop the recoding in each second and export blob to a wav file
const sleep = time => new Promise(resolve => setTimeout(resolve, time));

const asyncFn = async() => {
  for (let i = 0; i < maxNumOfSecs; i++) {
    if (recordingNotStopped) {
      rec.record();
      await sleep(trackLengthInMS);
      rec.stop();

      //stop microphone access
      gumStream.getAudioTracks()[0].stop();

      //Create the wav blob and pass it on to createWaveBlob
      rec.exportWAV(createWaveBlob);
    }
  }
}

function startRecording() {
  console.log("recordButton clicked");
  recordingNotStopped = true;
  var constraints = {
    audio: true,
    video: false
  }

  recordButton.disabled = true;
  stopButton.disabled = false;

  //Using the standard promise based getUserMedia() 
  navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {

    //Create an audio context after getUserMedia is called
    audioContext = new AudioContext();

    // Assign to gumStream for later use 
    gumStream = stream;

    //Use the stream 
    input = audioContext.createMediaStreamSource(stream);

    //Create the Recorder object and configure to record mono sound (1 channel)
    rec = new Recorder(input, {
      numChannels: 1
    });

    //Call the asynchronous function to split and export audio
    asyncFn();
    console.log("Recording started");

  }).catch(function(err) {
    //Enable the record button if getUserMedia() fails
    recordButton.disabled = false;
    stopButton.disabled = true;
  });
}

function stopRecording() {
  console.log("stopButton clicked");
  recordingNotStopped = false;

  //disable the stop button and enable the record button to  allow for new recordings
  stopButton.disabled = true;
  recordButton.disabled = false;

  //Set the recorder to stop the recording
  rec.stop();

  //stop microphone access
  gumStream.getAudioTracks()[0].stop();
}

function createWaveBlob(blob) {
  var url = URL.createObjectURL(blob);

  //Convert the blob to a wav file and call the sendBlob function to send the wav file to the server
  var convertedfile = new File([blob], 'filename.wav');
  sendBlob(convertedfile);
}

1 Ответ

0 голосов
/ 04 апреля 2019

Recorder.js хранит буфер записи аудио, которое он записывает.Когда вызывается exportWAV, буфер записи кодируется, но не очищается.Вам нужно будет вызвать clear на рекордере перед повторным вызовом record, чтобы предыдущий фрагмент аудио был очищен из буфера записи.

...