Search code examples
typescriptweb-audio-apiaudiocontextweb-mediarecorder

TypeScript record and play raw pcm audio


I am new to TypeScript, and the whole JavaScript environment in general. I have a small project to do, which requires creating a browser application with TypeScript (I don't have any code yet).

I need to record raw PCM audio from the browser microphone, log it, and play the same PCM audio back through browser speakers.

I have looked into using MediaRecorder for recording, and using the plain HTMLAudioElement for playback, but i'm not sure if they support RAW audio. I also some posts mentioning to use AudioContext ScriptProcessorNode to obtain raw audio, but i have no idea how to play them back.

I do not need completed solutions, but would appreciate any pointers or tutorials that would help me get this done.


Solution

  • I do work on a little library called extendable-media-recorder which allows to extend the native MediaRecorder with custom encoders. The proof-of-concept encoder that I build is a WAV encoder. It hope that works for you as well.

    I haven't documented the library yet which is why I'm happy to take your question as an opportunity to put together a complete usage example.

    import { MediaRecorder, register } from 'extendable-media-recorder';
    import { connect } from 'extendable-media-recorder-wav-encoder';
    
    (async () => {
        // Get the port a worker which can encode WAV files.
        const port = await connect();
        // Register this port with the MediaRecorder.
        await register(port);
        // Request a MediaStream with an audio track.
        const mediaStream = await navigator.mediaDevices
            .getUserMedia({ audio: true });
        // Create a MediaRecorder instance with the newly obtained MediaStream.
        const mediaRecorder = new MediaRecorder(mediaStream, {
            mimeType: 'audio/wav'
        });
    
        // Kick off the recording.
        mediaRecorder.start();
    
        mediaRecorder.addEventListener('dataavailable', ({ data }) => {
            // The data variable now holds a refrence to a Blob with the WAV file.
        });
    
        // Stop the recording after a second.
        setTimeout(() => mediaRecorder.stop(), 1000);
    })();
    

    I hope the comments do explain what the code does. Please let me know, if that's not the case.