I have an issue with my Ruby on rails 6 app. I make a video chat app with signaling-server js (WebRTC JS) and action-cable. video chat working fine on the same network in production. but it's not working on a different network. connection is established but video not streaming. it's not showing some error.
signaling_server.js file.
import consumer from "./channels/consumer";
// Broadcast Types
const JOIN_ROOM = "JOIN_ROOM";
const EXCHANGE = "EXCHANGE";
const REMOVE_USER = "REMOVE_USER";
// DOM Elements
let currentUser;
let localVideo;
let remoteVideoContainer;
let user;
// Objects
let pcPeers = {};
let localstream;
window.onload = () => {
user = document.getElementById("current-user");
if(user) {
currentUser = document.getElementById("current-user").innerHTML;
localVideo = document.getElementById("local-video");
remoteVideoContainer = document.getElementById("remote-video-container");
}
};
// Ice Credentials
const ice = { iceServers: [{ urls: "stun:stun.l.google.com:19302" }] };
// Add event listener's to buttons
document.addEventListener("DOMContentLoaded", () => {
const joinButton = document.getElementById("join-button");
const leaveButton = document.getElementById("leave-button");
joinButton.onclick = handleJoinSession;
leaveButton.onclick = handleLeaveSession;
});
// Initialize user's own video
document.onreadystatechange = () => {
if (document.readyState === "interactive") {
navigator.mediaDevices
.getUserMedia({
audio: true,
video: true,
})
.then((stream) => {
localstream = stream;
localVideo.srcObject = stream;
localVideo.muted = true;
})
.catch(logError);
}
};
const handleJoinSession = async () => {
consumer.subscriptions.create("VideoSessionChannel", {
connected: () => {
broadcastData({
type: JOIN_ROOM,
from: currentUser,
});
},
received: (data) => {
console.log("received", data);
if (data.from === currentUser) return;
switch (data.type) {
case JOIN_ROOM:
return joinRoom(data);
case EXCHANGE:
if (data.to !== currentUser) return;
return exchange(data);
case REMOVE_USER:
return removeUser(data);
default:
return;
}
},
});
};
const handleLeaveSession = () => {
for (let user in pcPeers) {
pcPeers[user].close();
}
pcPeers = {};
consumer.unsubscribe();
remoteVideoContainer.innerHTML = "";
broadcastData({
type: REMOVE_USER,
from: currentUser,
});
};
const joinRoom = (data) => {
createPC(data.from, true);
};
const removeUser = (data) => {
console.log("removing user", data.from);
let video = document.getElementById(`remoteVideoContainer+${data.from}`);
video && video.remove();
delete pcPeers[data.from];
};
const createPC = (userId, isOffer) => {
let pc = new RTCPeerConnection(ice);
pcPeers[userId] = pc;
console.log('createPC');
// for (const track of localstream.getTracks()) {
// pc.addTrack(track, localstream);
// }
pc.addStream(localstream);
isOffer &&
pc
.createOffer()
.then((offer) => {
console.log('createPC createOffer');
return pc.setLocalDescription(offer);
})
.then(() => {
broadcastData({
type: EXCHANGE,
from: currentUser,
to: userId,
sdp: JSON.stringify(pc.localDescription),
});
})
.catch(logError);
pc.onicecandidate = (event) => {
event.candidate &&
broadcastData({
type: EXCHANGE,
from: currentUser,
to: userId,
candidate: JSON.stringify(event.candidate),
});
};
pc.onaddstream = (event) => {
console.log(event.stream);
const element = document.createElement("video");
element.id = `remoteVideoContainer+${userId}`;
element.autoplay = "autoplay";
element.srcObject = event.stream;
remoteVideoContainer.appendChild(element);
};
pc.oniceconnectionstatechange = () => {
if (pc.iceConnectionState == "disconnected") {
console.log("Disconnected:", userId);
broadcastData({
type: REMOVE_USER,
from: userId,
});
}
};
return pc;
};
const exchange = (data) => {
let pc;
if (!pcPeers[data.from]) {
pc = createPC(data.from, false);
} else {
pc = pcPeers[data.from];
}
if (data.candidate) {
pc.addIceCandidate(new RTCIceCandidate(JSON.parse(data.candidate)))
.then(() => console.log("Ice candidate added"))
.catch(logError);
}
if (data.sdp) {
const sdp = JSON.parse(data.sdp);
pc.setRemoteDescription(new RTCSessionDescription(sdp))
.then(() => {
if (sdp.type === "offer") {
pc.createAnswer()
.then((answer) => {
console.log('exchange createAnswer');
return pc.setLocalDescription(answer);
})
.then(() => {
broadcastData({
type: EXCHANGE,
from: currentUser,
to: data.from,
sdp: JSON.stringify(pc.localDescription),
});
});
}
})
.catch(logError);
}
};
const broadcastData = (data) => {
/**
* Add CSRF protection: https://stackoverflow.com/questions/8503447/rails-how-to-add-csrf-protection-to-forms-created-in-javascript
*/
const csrfToken = document.querySelector("[name=csrf-token]").content;
const headers = new Headers({
"content-type": "application/json",
"X-CSRF-TOKEN": csrfToken,
});
fetch("sessions", {
method: "POST",
body: JSON.stringify(data),
headers,
});
};
const logError = (error) => console.warn("Whoops! Error:", error);
routes.rb file
mount ActionCable.server, at: "/cable"
Video Sessions Controller
class VideoSessionsController < ApplicationController
def create
head :no_content
ActionCable.server.broadcast "video_session_channel", session_params
end
private
def session_params
params.require(:video_session).permit(:type, :from, :to, :sdp, :candidate)
end
end
video channel file
class VideoSessionChannel < ApplicationCable::Channel
def subscribed
stream_from "video_session_channel"
end
end
video chat HTML file.
<span id="current-user"><%= @random_number %></span>
<div class="video-chat-content">
<div class="" id="remote-video-container"> </div>
<video id="local-video" autoplay></video>
</div>
Aucun commentaire:
Enregistrer un commentaire