I’m using expo 49 and react-native v0.72.3,
I seem to be getting video stream but it shows blank in RCTView however Local stream does show properly, Any help is much appreciated, I’m stuck
Here’s code :
import React, { useState, useEffect } from 'react';
import { View, Text, Button } from 'react-native';
import { RTCPeerConnection, RTCView, mediaDevices } from 'react-native-webrtc';
import socket from './socket';
import { SafeAreaView } from 'react-native-safe-area-context';
const STUN_SERVERS = [
];
const VideoCall = () => {
const [localStream, setLocalStream] = useState(null);
const [remoteStream, setRemoteStream] = useState(null);
const [peerConnections, setPeerConnections] = useState([]);
const socketInstance = socket()
useEffect(() => {
// Initialize local stream
mediaDevices.getUserMedia({ audio: true, video: true })
.then(stream => setLocalStream(stream))
.catch(error => console.error('Error getting user media:', error));
return () => {
socketInstance.disconnect(); // Clean up socketInstance connection on component unmount
};
}, []);
useEffect(() => {
if (localStream) {
// Create a peer connection for each user
const pc = new RTCPeerConnection({
iceServers: STUN_SERVERS,
sdpSemantics: 'unified-plan',
});
setPeerConnections(prevConnections => [...prevConnections, pc]);
// Add local stream to peer connection
localStream.getTracks().forEach(track => pc.addTrack(track, localStream));
// Handle ICE candidate events
pc.onicecandidate = event => {
if (event.candidate) {
// Send ICE candidate to all connected clients
socketInstance.emit('ice-candidate', { candidate: event.candidate });
}
};
// Handle remote stream events
pc.ontrack = event => {
setRemoteStream(event.streams[0]);
};
pc.onupdatetrack = event => {
// Update remoteStream if the video track changes
setRemoteStream(event.streams[0]);
};
}
}, [localStream]);
useEffect(()=>{
if (localStream){
socketInstance.on('offer', data => {
handleOffer(data);
});
}
}, [localStream])
const handleOffer = data => {
if (!localStream) {
console.error('Local stream is not yet available');
return;
}
const pc = new RTCPeerConnection({
iceServers: STUN_SERVERS,
sdpSemantics: 'unified-plan',
});
setPeerConnections(prevConnections => [...prevConnections, pc]);
pc.onicecandidate = event => {
if (event.candidate) {
socketInstance.emit('ice-candidate', { candidate: event.candidate });
}
};
pc.ontrack = event => {
const receivedOffer = data.offer.sdp;
if (receivedOffer.includes("audio") && receivedOffer.includes("video")) {
console.log("Received offer contains both audio and video.");
} else {
console.error("Received offer does not contain expected media types.");
}
console.log("Received tracks:", event.streams[0].getTracks()); // Log the tracks
// Check the kind of the track
if (event.track.kind === 'video') {
// Set remoteStream to the received video track
setRemoteStream(event.streams[0]);
}
};
pc.onupdatetrack = event => {
// Update remoteStream if the video track changes
setRemoteStream(event.streams[0]);
};
pc.setRemoteDescription(data.offer)
.then(() => pc.createAnswer())
.then(answer => {
console.log("Received offer:", data.offer.sdp); // Log the received offer
console.log("Created answer:", answer.sdp);
socketInstance.emit('answer', {
answer,
senderSocketId: data.senderUserId
});
return pc.setLocalDescription(answer);
});
};
useEffect(() => {
console.log('remote stream inUseeffect: ', remoteStream);
}, [remoteStream]);
const handleCall = () => {
// Send offer to all connected clients
peerConnections.forEach(pc => {
pc.createOffer()
.then(offer => {
// Send the offer to all clients
socketInstance.emit('offer', {
offer
});
pc.setLocalDescription(offer);
});
});
};
return (
<SafeAreaView>
<Text>Video Call Screen</Text>
{remoteStream && <RTCView streamURL={remoteStream.toURL()} zOrder={20} style={{ width: 200, height: 150 }} />}
{localStream && <RTCView streamURL={localStream.toURL()} zOrder={-1} style={{ width: 200, height: 150 }} />}
<Button title="Call" onPress={handleCall} />
</SafeAreaView>
);
};
export default VideoCall;
Here are my console logs:
LOG Received offer: v=0 o=- 589488281341570380 2 IN IP4 127.0.0.1 s=- t=0 0 a=group:BUNDLE 0 1 a=extmap-allow-mixed a=msid-semantic: WMS 4fdccd0d-4728-4c11-9c68-0e7c512277c8 m=audio 9 UDP/TLS/RTP/SAVPF 111 63 9 102 0 8 13 110 126 c=IN IP4 0.0.0.0 a=rtcp:9 IN IP4 0.0.0.0 a=ice-ufrag:ycdf a=ice-pwd:mMpVj3hpcTCUmEcmWnP2PC9c a=ice-options:trickle renomination a=fingerprint:sha-256 8F:E0:82:B4:B4:C3:8A:89:86:4C:14:3A:80:D5:7E:4B:3D:9C:02:79:32:EC:8D:54:A1:25:AF:9E:67:6B:81:41 a=setup:actpass a=mid:0 a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01 a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid a=sendrecv a=msid:4fdccd0d-4728-4c11-9c68-0e7c512277c8 49fdcbf9-aee6-4701-b070-97ff89e5113c a=rtcp-mux a=rtpmap:111 opus/48000/2 a=rtcp-fb:111 transport-cc a=fmtp:111 minptime=10;useinbandfec=1 a=rtpmap:63 red/48000/2 a=fmtp:63 111/111 a=rtpmap:9 G722/8000 a=rtpmap:102 ILBC/8000 a=rtpmap:0 PCMU/8000 a=rtpmap:8 PCMA/8000 a=rtpmap:13 CN/8000 a=rtpmap:110 telephone-event/48000 a=rtpmap:126 telephone-event/8000 a=ssrc:329664454 cname:HfRuU/4fxOIos/jP a=ssrc:329664454 msid:4fdccd0d-4728-4c11-9c68-0e7c512277c8 49fdcbf9-aee6-4701-b070-97ff89e5113c m=video 9 UDP/TLS/RTP/SAVPF 98 99 39 40 100 101 127 103 104 105 106 c=IN IP4 0.0.0.0 a=rtcp:9 IN IP4 0.0.0.0 a=ice-ufrag:ycdf a=ice-pwd:mMpVj3hpcTCUmEcmWnP2PC9c a=ice-options:trickle renomination a=fingerprint:sha-256 8F:E0:82:B4:B4:C3:8A:89:86:4C:14:3A:80:D5:7E:4B:3D:9C:02:79:32:EC:8D:54:A1:25:AF:9E:67:6B:81:41 a=setup:actpass a=mid:1 a=extmap:14 urn:ietf:params:rtp-hdrext:toffset a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time a=extmap:13 urn:3gpp:video-orientation a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01 a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid a=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id a=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id a=sendrecv a=msid:4fdccd0d-4728-4c11-9c68-0e7c512277c8 a4cbe637-2133-4354-a846-9c48b3eb178f a=rtcp-mux a=rtcp-rsize a=rtpmap:98 VP8/90000 a=rtcp-fb:98 goog-remb a=rtcp-fb:98 transport-cc a=rtcp-fb:98 ccm fir a=rtcp-fb:98 nack a=rtcp-fb:98 nack pli a=rtpmap:99 rtx/90000 a=fmtp:99 apt=98 a=rtpmap:39 AV1/90000 a=rtcp-fb:39 goog-remb a=rtcp-fb:39 transport-cc a=rtcp-fb:39 ccm fir a=rtcp-fb:39 nack a=rtcp-fb:39 nack pli a=rtpmap:40 rtx/90000 a=fmtp:40 apt=39 a=rtpmap:100 VP9/90000 a=rtcp-fb:100 goog-remb a=rtcp-fb:100 transport-cc a=rtcp-fb:100 ccm fir a=rtcp-fb:100 nack a=rtcp-fb:100 nack pli a=fmtp:100 profile-id=0 a=rtpmap:101 rtx/90000 a=fmtp:101 apt=100 a=rtpmap:127 VP9/90000 a=rtcp-fb:127 goog-remb a=rtcp-fb:127 transport-cc a=rtcp-fb:127 ccm fir a=rtcp-fb:127 nack a=rtcp-fb:127 nack pli a=fmtp:127 profile-id=2 a=rtpmap:103 rtx/90000 a=fmtp:103 apt=127 a=rtpmap:104 red/90000 a=rtpmap:105 rtx/90000 a=fmtp:105 apt=104 a=rtpmap:106 ulpfec/90000 a=ssrc-group:FID 4186340422 1365907217 a=ssrc:4186340422 cname:HfRuU/4fxOIos/jP a=ssrc:4186340422 msid:4fdccd0d-4728-4c11-9c68-0e7c512277c8 a4cbe637-2133-4354-a846-9c48b3eb178f a=ssrc:1365907217 cname:HfRuU/4fxOIos/jP a=ssrc:1365907217 msid:4fdccd0d-4728-4c11-9c68-0e7c512277c8 a4cbe637-2133-4354-a846-9c48b3eb178f
LOG Created answer: v=0 o=- 7187305411903491617 2 IN IP4 127.0.0.1 s=- t=0 0 a=group:BUNDLE 0 1 a=extmap-allow-mixed a=msid-semantic: WMS m=audio 9 UDP/TLS/RTP/SAVPF 111 63 9 102 0 8 13 110 126 c=IN IP4 0.0.0.0 a=rtcp:9 IN IP4 0.0.0.0 a=ice-ufrag:RjHl a=ice-pwd:nTACNClBNTkuMH3dcCqZdyQI a=ice-options:trickle renomination a=fingerprint:sha-256 A6:51:11:A2:60:09:A5:B7:7F:A4:40:5C:E0:6A:E9:68:79:83:0A:17:D7:75:CB:1E:BA:B0:02:9D:07:62:81:BA a=setup:active a=mid:0 a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01 a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid a=recvonly a=rtcp-mux a=rtpmap:111 opus/48000/2 a=rtcp-fb:111 transport-cc a=fmtp:111 minptime=10;useinbandfec=1 a=rtpmap:63 red/48000/2 a=fmtp:63 111/111 a=rtpmap:9 G722/8000 a=rtpmap:102 ILBC/8000 a=rtpmap:0 PCMU/8000 a=rtpmap:8 PCMA/8000 a=rtpmap:13 CN/8000 a=rtpmap:110 telephone-event/48000 a=rtpmap:126 telephone-event/8000 m=video 9 UDP/TLS/RTP/SAVPF 98 99 39 40 100 101 127 103 104 105 106 c=IN IP4 0.0.0.0 a=rtcp:9 IN IP4 0.0.0.0 a=ice-ufrag:RjHl a=ice-pwd:nTACNClBNTkuMH3dcCqZdyQI a=ice-options:trickle renomination a=fingerprint:sha-256 A6:51:11:A2:60:09:A5:B7:7F:A4:40:5C:E0:6A:E9:68:79:83:0A:17:D7:75:CB:1E:BA:B0:02:9D:07:62:81:BA a=setup:active a=mid:1 a=extmap:14 urn:ietf:params:rtp-hdrext:toffset a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time a=extmap:13 urn:3gpp:video-orientation a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01 a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid a=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id a=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id a=recvonly a=rtcp-mux a=rtcp-rsize a=rtpmap:98 VP8/90000 a=rtcp-fb:98 goog-remb a=rtcp-fb:98 transport-cc a=rtcp-fb:98 ccm fir a=rtcp-fb:98 nack a=rtcp-fb:98 nack pli a=rtpmap:99 rtx/90000 a=fmtp:99 apt=98 a=rtpmap:39 AV1/90000 a=rtcp-fb:39 goog-remb a=rtcp-fb:39 transport-cc a=rtcp-fb:39 ccm fir a=rtcp-fb:39 nack a=rtcp-fb:39 nack pli a=rtpmap:40 rtx/90000 a=fmtp:40 apt=39 a=rtpmap:100 VP9/90000 a=rtcp-fb:100 goog-remb a=rtcp-fb:100 transport-cc a=rtcp-fb:100 ccm fir a=rtcp-fb:100 nack a=rtcp-fb:100 nack pli a=fmtp:100 profile-id=0 a=rtpmap:101 rtx/90000 a=fmtp:101 apt=100 a=rtpmap:127 VP9/90000 a=rtcp-fb:127 goog-remb a=rtcp-fb:127 transport-cc a=rtcp-fb:127 ccm fir a=rtcp-fb:127 nack a=rtcp-fb:127 nack pli a=fmtp:127 profile-id=2 a=rtpmap:103 rtx/90000 a=fmtp:103 apt=127 a=rtpmap:104 red/90000 a=rtpmap:105 rtx/90000 a=fmtp:105 apt=104 a=rtpmap:106 ulpfec/90000
LOG Received offer contains both audio and video.
I haven’t tested it on IOS But it doesn’t work on android