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};