I have stream-view component. It successfully connects to the websocket when I run it locally, but when I expose vue app to the network via 'yarn dev --host' command and then try to connect to the same websocket it fails.
Template Section: This section defines the HTML template of the Vue component. It includes a video element bound to the properties id, ip, and controls. The video element is set to autoplay and muted, and its source is dynamically updated based on the incoming stream.
Script Setup Section: This section defines the JavaScript logic of the Vue component using the Composition API.
It defines a class Receiver responsible for managing the WebSocket connection and WebRTC communication.
The start method initializes the WebSocket connection and sets up event handlers for errors, close, and incoming messages.
The onIceServers method is triggered upon receiving ICE servers configuration from the server. It initializes the RTCPeerConnection with the received ICE servers, sets up event handlers, and creates an offer to establish a connection.
The onRemoteDescription method is triggered upon receiving a remote description (offer or answer) from the server. It sets the remote description for the peer connection.
The onIceCandidate method is triggered when a local ICE candidate is generated. It sends the candidate to the server.
The onRemoteCandidate method is triggered upon receiving a remote ICE candidate from the server. It adds the remote candidate to the peer connection.
The scheduleRestart method is responsible for handling connection restarts in case of errors or disconnections.
The props object defines the component's properties, ip and id, which are required for the component to function.
The onMounted hook initializes a new instance of the Receiver class when the component is mounted.
Overall, this component sets up a WebSocket connection to receive ICE servers configuration and establish a WebRTC connection for streaming video based on the provided IP address and ID. It handles various events and errors that may occur during the process.
<template>
<div class="flex justify-center items-stretch h-full w-full overflow-hidden my-0 mx-auto">
<video :id="`stream-view-${id}-${ip}`" :controls="false" playsinline autoplay muted
class="w-full block object-cover object-center" />
</div>
</template>
<script setup>
const restartPause = 2000;
class Receiver {
constructor(ip, id) {
this.ip = ip;
this.id = id;
this.terminated = false;
this.ws = null;
this.pc = null;
this.restartTimeout = null;
this.start();
}
start() {
try {
console.log("connecting");
this.ws = new WebSocket(`ws://172.20.10.12:8889/stream/${this.id}`);
this.ws.onerror = () => {
console.log("ws error");
if (this.ws === null) {
return;
}
this.ws.close();
this.ws = null;
};
this.ws.onclose = () => {
console.log("ws closed");
this.ws = null;
this.scheduleRestart();
};
this.ws.onmessage = (msg) => this.onIceServers(msg);
} catch (e) {
console.log(e, 'error while connecting')
}
}
onIceServers(msg) {
try {
if (this.ws === null) {
return;
}
const iceServers = JSON.parse(msg.data);
this.pc = new RTCPeerConnection({
iceServers,
});
this.ws.onmessage = (msg) => this.onRemoteDescription(msg);
this.pc.onicecandidate = (evt) => this.onIceCandidate(evt);
this.pc.oniceconnectionstatechange = () => {
if (this.pc === null) {
return;
}
console.log("peer connection state:", this.pc.iceConnectionState);
switch (this.pc.iceConnectionState) {
case "disconnected":
this.scheduleRestart();
}
};
this.pc.ontrack = (evt) => {
console.log("new track " + evt.track.kind);
document.getElementById(`stream-view-${this.id}-${this.ip}`).srcObject = evt.streams[0];
};
const direction = "sendrecv";
this.pc.addTransceiver("video", { direction });
this.pc.addTransceiver("audio", { direction });
this.pc.createOffer()
.then((desc) => {
if (this.pc === null || this.ws === null) {
return;
}
this.pc.setLocalDescription(desc);
console.log("sending offer", desc);
this.ws.send(JSON.stringify(desc));
})
} catch (e) {
console.log(e, 'error while onIceServers')
}
}
onRemoteDescription(msg) {
try {
if (this.pc === null || this.ws === null) {
return;
}
this.pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(msg.data)));
this.ws.onmessage = (msg) => this.onRemoteCandidate(msg);
} catch (e) {
console.log(e, 'error while onRemoteDescription')
}
}
onIceCandidate(evt) {
try {
if (this.ws === null) {
return;
}
if (evt.candidate !== null) {
if (evt.candidate.candidate !== "") {
this.ws.send(JSON.stringify(evt.candidate));
}
}
} catch (e) {
console.log(e, 'error while onIceCandidate')
}
}
onRemoteCandidate(msg) {
try {
if (this.pc === null) {
return;
}
this.pc.addIceCandidate(JSON.parse(msg.data));
} catch (e) {
console.log(e, 'error while onRemoteCandidate')
}
}
scheduleRestart() {
try {
if (this.terminated) {
return;
}
if (this.ws !== null) {
this.ws.close();
this.ws = null;
}
if (this.pc !== null) {
this.pc.close();
this.pc = null;
}
this.restartTimeout = window.setTimeout(() => {
this.restartTimeout = null;
this.start();
}, restartPause);
} catch (e) {
console.log(e, 'error while scheduleRestart')
}
}
}
const props = defineProps({
ip: {
type: String,
required: true
},
id: {
type: String,
required: true
}
});
onMounted(() => {
new Receiver(props.ip, props.id);
});
</script>
I tried to connect to a websocket through a vue app that is running locally.