Search code examples
firefoxaudiovideo-streamingweb-mediarecorder

Control volume gain for Video/Audio stream in Firefox


I'm trying to record Video/Audio files using MediaRecorder API for Firefox.

When I'm using web Audio API for creating the nodes (source -> Gain -> Destination)

The output of the recorded file is only Audio as the return stream from the destination node is Audio stream only referring to this documentation https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamAudioDestinationNode

Any suggestion for getting Audio/video stream in the destination output to record audio/video not audio only.

    var mediastream;

    var ctx = new AudioContext();

    var mediaStreamSource = ctx.createMediaStreamSource(mediaStream); 

    var destination = ctx.createMediaStreamDestination();

    ObjectStore.VolumeGainNode = ctx.createGain();
    ObjectStore.VolumeGainNode.gain.value = 0.5;

    mediaStreamSource.connect(ObjectStore.VolumeGainNode);

    ObjectStore.VolumeGainNode.connect(destination);

    mediaStream = destination.stream;

Solution

  • You need a stream composed of the gUM video track and your gain-modified audio track.

    Following the standard, Firefox lets you modify tracks in a stream using stream.addTrack and stream.removeTrack, as well as compose new streams out of tracks with new MediaStream([tracks]).

    This lets you solve your problem by replacing the gUM audio track with your gain-manipulated one:

    var constraints = { video: true, audio: true };
    
    var start = () => navigator.mediaDevices.getUserMedia(constraints)
      .then(stream => modifyGain(video.srcObject = stream, 0.5))
      .catch(e => console.error(e));
    
    var modifyGain = (stream, gainValue) => {
        var audioTrack = stream.getAudioTracks()[0];
        var ctx = new AudioContext();
        var src = ctx.createMediaStreamSource(new MediaStream([audioTrack]));
        var dst = ctx.createMediaStreamDestination();
        var gainNode = ctx.createGain();
        gainNode.gain.value = gainValue;
        [src, gainNode, dst].reduce((a, b) => a && a.connect(b));
        stream.removeTrack(audioTrack);
        stream.addTrack(dst.stream.getAudioTracks()[0]);
    };
    

    Here's the fiddle (Firefox 44 or newer): https://jsfiddle.net/7wd2z8rz/

    Again with MediaRecorder: https://jsfiddle.net/j33xmkcq/