Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Post-processing #198

Open
giuseppeg opened this issue Oct 6, 2021 · 0 comments
Open

Post-processing #198

giuseppeg opened this issue Oct 6, 2021 · 0 comments

Comments

@giuseppeg
Copy link

giuseppeg commented Oct 6, 2021

Hi there this library looks dope!

How hard would it be to do the conversion later instead of doing it in real time?
I assume I'd need to derive the solution from https://github.com/elsmr/mp3-mediarecorder/blob/master/src/worker/index.ts

I want to encode an audio file acquired with the native MediaRecorder API, so I am using this library worker with a custom "frontend" see implementation below and the issue right after

// Given:
// recording = [Blob]

const worker = new Worker(new URL("../lib/worker.ts", import.meta.url));
const PostMessageType = {
  DATA_AVAILABLE: "DATA_AVAILABLE",
  START_RECORDING: "START_RECORDING",
  STOP_RECORDING: "STOP_RECORDING",
  ERROR: "ERROR",
  BLOB_READY: "BLOB_READY",
  WORKER_RECORDING: "WORKER_RECORDING",
};

let onComplete;
const audioBlobPromise = new Promise((resolve) => {
  onComplete = resolve;
});

worker.addEventListener("message", (event) => {
  const message = event.data;
  switch (message.type) {
    case PostMessageType.WORKER_RECORDING: {
      // Send the chunks received by the MediaRecorder to the worker for encoding
      // recording = [Blob]
      const context = new AudioContext();
      Promise.all(
        recording.map((r) =>
          r.arrayBuffer().then((arrayBuffer) => {
            let onSuccess, onError;
            const decodeAudioDataPromise = new Promise(
              (resolve, reject) => {
                onSuccess = (buffer) => {
                  const data = buffer.getChannelData(0);
                  worker.postMessage({
                    type: PostMessageType.DATA_AVAILABLE,
                    data,
                  });
                  Promise.resolve().then(() => {
                    resolve();
                  });
                };
                onError = () => {
                  reject();
                };
              }
            );
            context.decodeAudioData(arrayBuffer, onSuccess, onError);
            return decodeAudioDataPromise;
          })
        )
      )
        .then(() => {
          // End the encoding. It will result in PostMessageType.BLOB_READY.
          setTimeout(() => {
            worker.postMessage({ type: PostMessageType.STOP_RECORDING });
          }, 1000);
        })
        .finally(() => {
          context.close();
        });
      break;
    }
    case PostMessageType.BLOB_READY: {
      mimeType = "audio/mpeg";
      onComplete([message.blob]);
      break;
    }
    default: {
      console.error(
        "An error occured while encoding the recording ",
        message.error || "unknown error"
      );
      onComplete(recording);
    }
  }
});

// Start the encoder
worker.postMessage({
  type: PostMessageType.START_RECORDING,
  config: { sampleRate: 44100 },
});

const audioBlob = await audioBlobPromise;
worker.terminate();
console.log({ audioBlob });

new File(audioBlob, `recording.mp3`, {
  lastModified: Date.now(),
  type: mimeType,
})

With this when I send data to the worker, the handler throws an error here because encodedBytesAmount is -1:

const encodedBytesAmount = vmsgInstance.vmsg_encode(vmsgRef, data.length);
if (encodedBytesAmount < 0) {
throw new Error('encoding_failed');
}

{ data: Float32Array(246077)}, dataLength: 246077, encodedBytesAmount: -1 }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant