How do I reduce background noise in my webrtc app?

276 Views Asked by At

I'm trying to create a WebRTC player using React and the simple peer library. I'm able to make video calls successfully, but there is a lot of background noise during my calls. I'm not sure how to fix it. I've tried extracting the audio from the media stream and passing it through a biquad filter. This is the first time I've ever worked with noise reduction. Any advice would be appreciated.

VideoPlayer.js

import { SocketContext } from "./Context";
import { useContext, useEffect, useRef } from "react";
import { useNavigate } from "react-router-dom";

function Videoplayer() {
    const navigate = useNavigate();
    const { id, me, audioSrc, callAccepted,  userVideo, callEnded, stream } = useContext(SocketContext);
    const audioContainer = useRef();

    useEffect(() => {
        if(audioContainer.current) 
            audioContainer.current.appendChild(audioSrc);
    }, [audioContainer, audioSrc]);

    return (
        <div>
            { //ensures your video stream is enabled b4 enabling other user's video
                stream && callAccepted && !callEnded && ( 
                    <>
                        <video playsInline ref={userVideo} autoPlay></video>
                        <div ref={audioContainer}></div>
                    </>
                )
            }
        </div>
    )
}

export default Videoplayer;

Context.js

import React, {createContext, useState, useRef, useEffect} from 'react';
import {io} from 'socket.io-client';
import Peer from 'simple-peer';

const SocketContext = createContext();
var server = process.env.REACT_APP_SERVER;
const socket = io(server);

function ContextProvider({children}, props)  {
    const [stream, setStream] = useState(null);
    const [me, setMe] = useState('');
    const [call, setCall] = useState(null);
    const [callEnded, setCallEnded] = useState(null);
    const [callAccepted, setCallAccepted] = useState(null);
    const [name, setName] = useState('');
    const myVideo = useRef();
    const userVideo = useRef();
    const connectionRef = useRef();
    var url = new URLSearchParams(window.location.search);
    var id = url.get("id");
    const [peerSocket, setPeerSocket] = useState('');
    const [audioSrc, setAudioSrc] = useState(null);

    useEffect(() => {
        navigator.mediaDevices.getUserMedia({audio: true, video: true})
        .then((stream) => {
            setStream(stream);
            if (myVideo.current)
                myVideo.current.srcObject = stream;

                const ctx = new AudioContext();
                const gainNode = ctx.createGain();
                const audioDest = ctx.createMediaStreamDestination();
                const source = ctx.createMediaStreamSource(stream);
    
                const biquadFilter = ctx.createBiquadFilter();
                biquadFilter.type = 'lowshelf';
                biquadFilter.frequency.value = 1000;
                biquadFilter.gain.value = 1;
                source.connect(biquadFilter);
                biquadFilter.connect(ctx.destination);
                /*gainNode.connect(audioDest);
                gainNode.gain.value = 0.15;   
                source.connect(gainNode);*/
                
                /*const audio = new Audio();
                audio.controls = true;
                audio.autoplay = true;
                audio.srcObject = audioDest.stream;
                audio.play();
                setAudioSrc(audio);*/
        });

        socket.on('me', (userId) => {
            setMe(userId);
            socket.emit('join', id, userId);
            console.log('my id: ' + userId)
        });

        socket.on('enter-session', peerId => {
            setPeerSocket(peerId);
            console.log('peer session id: ' + peerId)
        });

        socket.on('callUser', ({from, name: callerName, signal}) => {
            setCall({isReceivedCall: true, from, name: callerName, signal});
        });
    }, []);

    function callUser(id) {
        if(id == '') {
            console.log('empty')
            return;
        }

        var peer = new Peer({initiator: true, trickle: false, stream});
        peer.on('signal', (data) => {
            console.log('calling ' + id)
            socket.emit('callUser', {userToCall: id, signalData: data, from: me, name})
        });
        peer.on('stream', (stream) => {
            console.log('caller gets remote video stream')
            if(userVideo.current)
                userVideo.current.srcObject = stream;
        });
        socket.on('callAccepted', (signal) => {
            console.log('accepting call')
            setCallAccepted(true);
            peer.signal(signal);
        });
        connectionRef.current = peer;
    }

    function answerCall() {
        if (call == null) {
            console.log('no call')
            return;
        }
        
        setCallAccepted(true);
        var peer = new Peer({initiator: false, trickle: false, stream});
        peer.on('signal', (data) => {
            socket.emit('answerCall', {signal: data, to: call.from});
            console.log('answering ' + call.from)
        });
        peer.on('stream', (stream) => {
            console.log('peer gets remote video stream')
            if(userVideo.current)
                userVideo.current.srcObject = stream;
        });
        peer.signal(call.signal);
        connectionRef.current = peer;
    }

    function leaveCall() {
        setCallEnded(true);
        connectionRef.current.destroy();
        window.location.reload();
    }

    return(
        <SocketContext.Provider value={{ audioSrc, socket, id, call, callAccepted, userVideo, stream, name, setName, callEnded, me, callUser, leaveCall, answerCall}}>
            {children}
        </SocketContext.Provider>
    )
};

export {ContextProvider, SocketContext};
0

There are 0 best solutions below