import React, { useEffect, useRef, useState, useCallback } from ‘react’;
import io from ‘socket.io-client’;
import * as mediasoupClient from “mediasoup-client”;
import ReactPlayer from ‘react-player’;
import {increment, decrement, reset} from ‘…/src/redux-elements/Features/demoSlice’;
import { useDispatch, useSelector } from ‘react-redux’;
import { setLocalStream, addRemoteStream, removeRemoteStream, setError } from ‘…/src/redux-elements/Features/streamSlice’;
import VideoPlayer from ‘./VideoPlayer’;
import {selectRoomName, setRoomName} from ‘./redux-elements/Features/roomReducer’
// install react-video-stream k
const Controls = ({ startVideo, stopVideo, startScreenShare, stopScreenShare }) => (
//dvff
const App = () => {
const dispatch = useDispatch();
//State Variables
const count = useSelector(state => state.demo.count);
const roomName = useSelector(selectRoomName)
//fcccc
const socket = useRef(io(“/mediasoup”));
const videoContainerRef = useRef(null);
const [socketInstance, setSocketInstance] = useState(null);
const [connected, setConnected] = useState(false);
const [localStream, setLocalStream] = useState(null);
const [remoteStreams, setRemoteStreams] = useState();
const [error, setError] = useState(null);
const [mediaSoupdevice, setmediaSoupdevice] = useState({});
const [producerTransport, setProducerTransport] = useState(null);
const [consumerTransports, setConsumerTransports] = useState();
const [audioProducer, setAudioProducer] = useState(null);
const [videoProducer, setVideoProducer] = useState(null);
const [consumer, setConsumer] = useState(null);
const [consumingTransports, setConsumingTransports] = useState();
const [ routerRtpCapabilities, setRouterRtpCapabilities] = useState(null);
const [ newConsumerTransport, setNewConsumerTransport] = useState(null)
const [params, setParams] = useState(null);
useEffect(()=> {
const room = window.location.pathname.split('/')[2];
dispatch(setRoomName(room));
console.log("room name from the path paramter is", roomName);
}, )
useEffect(() => {
const socketInstance = io('https://localhost:3000/mediasoup');
socketInstance.on('connect', () => {
console.log('Connected to server!');
socket.current = socketInstance;
setSocketInstance(socket.current);
setConnected(true);
getLocalStream();
});
socketInstance.on('connection-success', ({ socketId }) => {
console.log('Connection successful! Socket ID:', socketId);
});
return () => {
socketInstance.disconnect();
};
}, );
//UseEffect to call the join room function
useEffect(() => {
if (socketInstance && roomName != null) {
joinRoom();
}
}, [socketInstance, roomName]);
let Videoparams = {
encodings: [
{
rid: ‘r0’,
maxBitrate: 100000,
scalabilityMode: ‘S1T3’,
},
{
rid: ‘r1’,
maxBitrate: 300000,
scalabilityMode: ‘S1T3’,
},
{
rid: ‘r2’,
maxBitrate: 900000,
scalabilityMode: ‘S1T3’,
},
],
// mediasoup :: API
codecOptions: {
videoGoogleStartBitrate: 1000
}
}
const [videoParams, setVideoParams] = useState({Videoparams}); //okx
const [audioParams, setAudioParams] = useState({}); //ok
const joinRoom = () => {
socket.current.emit(‘joinRoom’, { roomName: roomName }, (data) => {
if (data && data.rtpCapabilities) {
console.log(“RTP Capabilities received from server:”, data.rtpCapabilities);
setRouterRtpCapabilities(data.rtpCapabilities);
} else {
console.log("Unable to retrieve RTP capabilities from server");
}
});
};
useEffect(() => {
if (routerRtpCapabilities) {
createDevice();
}
}, [routerRtpCapabilities]);
const createDevice = useCallback(async () => {
try {
const device = new mediasoupClient.Device();
setmediaSoupdevice(device);
await device.load({ routerRtpCapabilities });
} catch (error) {
console.error(error);
if (error.name === ‘UnsupportedError’) {
console.warn(‘Browser not supported’);
}
}
}, [routerRtpCapabilities]);
//UseEffect to call CreateSendTransport Function
useEffect(()=> {
createSendTransport();
}, [mediaSoupdevice])
const createSendTransport = () => {
socket.current.emit(‘createWebRtcTransport’, { consumer: false }, async ({ params}) => {
if (params.error) {
console.error(“params error”, params.error);
return;
}
console.log("Params received from Server to create sendTransport", params);
console.log("mediasoup device::", mediaSoupdevice);
const newProducerTransport = await mediaSoupdevice.createSendTransport(params);
console.log("newProducerTransport", newProducerTransport); // Log the newProducerTransport
if (newProducerTransport) {
setProducerTransport(newProducerTransport);
newProducerTransport.on('connect', async ({ dtlsParameters }, callback, errback) => {
try {
await socket.current.emit('transport-connect', { dtlsParameters });
callback();
} catch (error) {
errback(error);
}
});
newProducerTransport.on('produce', async (parameters, callback, errback) => {
console.log("New Producer Transport :::>>", parameters);
try {
await socket.current.emit('transport-produce', {
kind: parameters.kind,
rtpParameters: parameters.rtpParameters,
appData: parameters.appData,
}, ({ id, producersExist }) => {
callback({ id });
if (producersExist) getProducers();
});
} catch (error) {
errback(error);
}
});
} else {
console.log("Unable to create Producer Transport");
}
});
};
//function to get the localStream ::>>
const getLocalStream = () => {
navigator.mediaDevices.getUserMedia({
audio: true,
video: {
width: { min: 640, max: 1920 },
height: { min: 400, max: 1080 }
}
}).then((stream) => {
setLocalStream(stream);
const AudioTracks = stream.getAudioTracks()[0];
const videoTracks = stream.getVideoTracks()[0];
setAudioParams({ track: AudioTracks, ...audioParams });
setVideoParams({ track: videoTracks, ...videoParams });
console.log("audio track", AudioTracks );
console.log("vd track", videoTracks );
}).catch(error => {
console.error(‘Error accessing media devices:’, error);
setError(error.message);
});
};
//Connect Send Tranport function::>
useEffect(() => {
const connectSendTransport = async() => {
if (!producerTransport) return;
console.log("producerTransport", producerTransport);
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
const videoTrack = stream.getVideoTracks( )[0];
if (producerTransport) {
const stats = await producerTransport.getStats();
console.log("Stats for producerTransport:", stats);
}
const newProducer = await producerTransport.produce({
track : videoTrack,
encodings :
[
{ maxBitrate: 100000 },
{ maxBitrate: 300000 },
{ maxBitrate: 900000 }
],
codecOptions :
{
videoGoogleStartBitrate : 1000
}
})
console.log("Log for new Producer >>>>>>>>>>>>>.", newProducer);
setVideoProducer(newProducer)
// newAudioProducer.on('trackended', () => console.log('Audio track ended'));
// newAudioProducer.on('transportclose', () => console.log('Audio transport ended'));
newProducer.on('trackended', () => console.log('Video track ended'));
newProducer.on('transportclose', () => console.log('Video transport ended'));
};
if(producerTransport) {
connectSendTransport();
}
}, [producerTransport])
//Function for SignalNewConsumer Transport::>
const signalNewConsumerTransport = async (remoteProducerId) => {
if (consumingTransports.includes(remoteProducerId)) return;
consumingTransports.push(remoteProducerId);
await socket.current.emit(‘createWebRtcTransport’, { consumer: true }, async ({ params }) => {
if (!params || params.error) {
console.error(params ? params.error : “Params are null or undefined”);
return;
}
console.log(`Signal PARAMS received from Server... ${params}`);
setParams(params);
let ConsumerTransport;
try {
ConsumerTransport = await mediaSoupdevice.createRecvTransport(params);
setNewConsumerTransport(ConsumerTransport);
ConsumerTransport.on('connect', async ({ dtlsParameters }, callback, errback) => {
try {
await socket.current.emit('transport-recv-connect', {
dtlsParameters,
serverConsumerTransportId: params.id,
});
callback();
} catch (error) {
errback(error);
}
});
connectRecvTransport(ConsumerTransport, remoteProducerId, params.id);
} catch (error) {
console.log("error in Consumer Transport", error)
}
});
};
// server informs the client of a new producer just joined
socket.current.on(‘new-producer’, ({ producerId }) => signalNewConsumerTransport(producerId))
const getProducers = () => {
socket.current.emit(‘getProducers’, producerIds => {
console.log(“Get Producers Information ::>>>>>”, producerIds)
// for each of the producer create a consumer
// producerIds.forEach(id => signalNewConsumerTransport(id))
producerIds.forEach(signalNewConsumerTransport)
})
}
const connectRecvTransport = async (consumerTransport, remoteProducerId, serverConsumerTransportId) => {
// for consumer, we need to tell the server first
// to create a consumer based on the rtpCapabilities and consume
// if the router can consume, it will send back a set of params as below
await socket.current.emit(‘consume’, {
rtpCapabilities: mediaSoupdevice.rtpCapabilities,
remoteProducerId,
serverConsumerTransportId,
}, async ({ params }) => {
if (params.error) {
console.error(‘Cannot Consume’);
return;
}
console.log(Consumer Params ${params}
);
// then consume with the local consumer transport
// which creates a consumer
const consumer = await consumerTransport.consume({
id: params.id,
producerId: params.producerId,
kind: params.kind,
rtpParameters: params.rtpParameters
});
setConsumerTransports([...consumerTransports, {
consumerTransport,
serverConsumerTransportId: params.id,
producerId: remoteProducerId,
consumer
}]);
// destructure and retrieve the video track from the producer
const { track } = consumer
const rstream = new MediaStream([track]);
console.log("Remote Stream after adding track:", rstream);
setRemoteStreams(prevStreams => [...prevStreams, rstream]); // Update using functional form of setState
});
};
useEffect(()=> {
console.log(“rm stream…”, remoteStreams);
}, [remoteStreams])
//Video Controller Functionss
const startVideo = () => {
if (localStream) {
localStream.getVideoTracks().forEach(track => {
track.enabled = true;
});
}
};
const stopVideo = () => {
if (localStream) {
localStream.getVideoTracks().forEach(track => {
track.enabled = false;
});
}
};
const startScreenShare = () => {
navigator.mediaDevices.getDisplayMedia({ video: true }).then((stream) => {
const screenTrack = stream.getVideoTracks()[0];
setVideoParams({ …videoParams, track: screenTrack });
if (videoContainerRef.current) {
videoContainerRef.current.srcObject = stream;
}
screenTrack.onended = () => {
setVideoParams({ …videoParams, track: localStream.getVideoTracks()[0] });
if (videoContainerRef.current) {
videoContainerRef.current.srcObject = localStream;
}
};
}).catch(error => {
console.error(‘Error accessing screen share:’, error);
});
};
const stopScreenShare = () => {
if (!localStream || !localStream.getVideoTracks().length) {
console.error(‘Error: localStream does not exist or does not have any video tracks’);
return;
}
try {
setVideoParams({ ...videoParams, track: localStream.getVideoTracks()[0] });
if (videoContainerRef.current) {
videoContainerRef.current.srcObject = localStream;
}
} catch (error) {
console.error('Error in stopScreenShare:', error);
}
};
useEffect(()=> {
console.log(“remote stream received…>”);
}, [remoteStreams])
const renderRemoteStreams = () => {
return remoteStreams.map((remoteStream, index) => (
));
};
//dfdedfv
return (
{/*
Counter: {count}
dispatch(increment())}>Increment dispatch(decrement())}>Decrement dispatch(reset())}>Reset {error && <div>Error: {error}</div>}
{/* Controls for starting/stopping video and sdreen sharing */}
<Controls
startVideo={startVideo}
stopVideo={stopVideo}
startScreenShare={startScreenShare}
stopScreenShare={stopScreenShare}
/>
{/* Container for local fvidfffffeoffffff stddream*/}
<div>
<ReactPlayer url={localStream} width="300px" height="200px" playing={true} />
</div>
<div>
{remoteStreams.length > 0 ? (
renderRemoteStreams()
) : (
<h5>No Remote Streams Available</h5>
)}
</div>
</div>
);
};
export default App;
video Player:
import React, { useEffect, useRef } from ‘react’;
const VideoPlayer = ({ stream }) => {
const videoRef = useRef();
useEffect(() => {
if (videoRef.current && stream instanceof MediaStream) {
videoRef.current.srcObject = stream;
}
}, [stream]);
return
export default VideoPlayer;
i am getting black screen