WebRTC - 如何调整视频流上的麦克风音量?

WebRTC - How to adjust microphone volume on a video stream?

我正在尝试调整使用 2 个视频进行流式传输的 WebRTC 聊天应用程序中的麦克风音量。 可以修改麦克风的增益吗?如果是,我该如何对我正在使用的以下流执行此操作?

/*********************** video call ***************************/
var localStream;

var localVideo = document.getElementById("localVideo");
var remoteVideo = document.getElementById("remoteVideo");
var callButton = document.getElementById("callButton");

var inputLevelSelector = document.getElementById('mic-volume');
var outputLevelSelector = document.getElementById('speaker-volume');
inputLevelSelector.addEventListener('change', changeMicrophoneLevel);
outputLevelSelector.addEventListener('change', changeSpeakerLevel);

callButton.disabled = true;
callButton.onclick = call;

navigator.getUserMedia = navigator.getUserMedia ||
    navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
navigator.getUserMedia({
        audio: true,
        video: true
    }, gotStream, //note that we are adding both audio and video
    function (error) {
        console.log(error);
    });

var RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
var SessionDescription = window.RTCSessionDescription || window.mozRTCSessionDescription || window.webkitRTCSessionDescription;
var pc = new RTCPeerConnection({
    "iceServers": []
});

function gotStream(stream) {
    // localVideo.src = window.URL.createObjectURL(stream); // DEPRECATED
    localVideo.srcObject = stream; // UPDATED
    localStream = stream;
    callButton.disabled = false;
    pc.addStream(stream);
}

pc.onicecandidate = function (event) {
    console.log(event);
    if (!event || !event.candidate) {
        return;
    } else {
        socket.emit("video call", {
            type: "iceCandidate",
            "candidate": event.candidate
        });
    }
};

var remoteStream;
pc.onaddstream = function (event) {
    remoteStream = event.stream;
    var remoteVideo = document.getElementById("remoteVideo");
    // remoteVideo.src = window.URL.createObjectURL(event.stream); // DEPRECATED
    remoteVideo.srcObject = event.stream; // UPDATED
    remoteVideo.play();
};

请注意我是新手,请放心! :)

在下面,我实现了我在评论中分享的 post。这是相同的设置,但包含您的代码。

您首先从网络音频创建节点 API。因为你想操纵流的音量,所以你需要 MediaStreamAudioSourceNode, a MediaStreamAudioDestinationNode and a GainNodeMediaStreamAudioSourceNode 是流的入口点。通过在此处注入它,我们可以通过增益将其连接起来。流将通过音量控制的 GainNode,然后传递到 MediaStreamAudioDestinationNode,您可以在 RTC 客户端中再次使用该流。

从那里使用您从 MediaStreamAudioDestinationNode.stream 属性.

获得的流

编辑:

事实证明,MediaStreamAudioDestinationNode.stream 是一个只有音轨的 MediaStream 对象。因此视频已从流中删除,必须重新加入。

因此,当您能够访问流时,从流中获取视频轨道并将它们存储在变量中。然后在通过网络音频 API 传递流后,将视频轨道与通过 GainNode.

的音轨连接起来
var inputLevelSelector = document.getElementById('mic-volume');

// Renamed the variable after your comment.
var peerConnection = new RTCPeerConnection({
    "iceServers": []
});

function gotStream(stream) {

  // Get the videoTracks from the stream.
  const videoTracks = stream.getVideoTracks();

  /**
   * Create a new audio context and build a stream source,
   * stream destination and a gain node. Pass the stream into 
   * the mediaStreamSource so we can use it in the Web Audio API.
   */
  const context = new AudioContext();
  const mediaStreamSource = context.createMediaStreamSource(stream);
  const mediaStreamDestination = context.createMediaStreamDestination();
  const gainNode = context.createGain();

  /**
   * Connect the stream to the gainNode so that all audio
   * passes through the gain and can be controlled by it.
   * Then pass the stream from the gain to the mediaStreamDestination
   * which can pass it back to the RTC client.
   */
  mediaStreamSource.connect(gainNode);
  gainNode.connect(mediaStreamDestination);

  /**
   * Change the gain levels on the input selector.
   */
  inputLevelSelector.addEventListener('input', event => {
    gainNode.gain.value = event.target.value;
  });

  /**
   * The mediaStreamDestination.stream outputs a MediaStream object
   * containing a single AudioMediaStreamTrack. Add the video track
   * to the new stream to rejoin the video with the controlled audio.
   */
  const controlledStream = mediaStreamDestination.stream;
  for (const videoTrack of videoTracks) {
    controlledStream.addTrack(videoTrack);
  }

  /**
   * Use the stream that went through the gainNode. This
   * is the same stream but with altered input volume levels.
   */
  localVideo.srcObject = controlledStream;
  localStream = controlledStream;
  peerConnection.addStream(controlledStream);
  callButton.disabled = false;

}