I'm trying to create a video call app using Socket.io, PeerJS, Node, Express and Angular.
The issue is that, while I can connect my own video just fine, I can't see the other user's video. In fact, the Peer.on('call') code doesn't seem to trigger at all.
I think there might also be an issue with my index.js code, because the console.log()s I've added to that file never appear either and I get the following error message:
Failed to load resource: the server responded with a status of 404 (Not Found)
My code looks like this:
// --- index.js:
const express = require("express");
const app = express();
const PORT = 3000;
const path = require('path');
app.set('src', path.join(__dirname, '../src'));
const server = require('http').Server(app)
const io = require('socket.io')(server)
io.on('connection',(socket)=>{
console.log('backend video test 1') // THIS NEVER TRIGGERS
socket.on('join-room',(roomId,userId)=>{
//join the room
console.log('backend video test 2') // THIS NEVER TRIGGERS
socket.join(roomId)
socket.to(roomId).broadcast.emit('user-connected',userId)
//leave room
socket.on('disconnect',()=>{
console.log('backend video test 3') // THIS NEVER TRIGGERS
socket.to(roomId).broadcast.emit('user-diconncected',userId)
})
})
})
app.listen(PORT, console.log(`Your app is running on port ${PORT}`))
// --- component ts file:
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Socket } from 'ngx-socket-io';
import { Peer } from "peerjs";
interface VideoElement{
muted:boolean;
srcObject:MediaStream;
userId:string;
}
@Component({
selector: 'app-video-call-v2',
templateUrl: './video-call-v2.component.html',
styleUrls: ['./video-call-v2.component.css']
})
export class VideoCallV2Component implements OnInit {
currentUserId:string='testUser'+Math.floor(Math.random()*1000);
videos:VideoElement[]=[];
constructor(
private route: ActivatedRoute,
private socket: Socket,
) {}
ngOnInit() {
console.log(`Init Peer with id ${this.currentUserId}`) // this works fine.
//------------------------------------
// --- Access user video and audio ---
//------------------------------------
navigator.mediaDevices.getUserMedia({
audio:true,
video:true
}).catch((err)=>{
console.log('user media error: ',err);
return null
}).then((stream:any)=>{
const myPeer = new Peer(this.currentUserId,{
host:'/',
port:3001,
});
console.log('myPeer =');
console.log(myPeer) // this works fine.
myPeer.on('open',(userId: any)=>{
console.log('test2') // this works fine.
console.log(userId) // this works fine.
this.socket.emit('join-room','lessonvideo2',userId)
});
if (stream){
this.addMyVideo(stream);
console.log(stream) // this works fine.
} else{
console.log('no stream found')
}
//-------------------------------
// --- Receieve incoming call ---
//-------------------------------
myPeer.on('call',call=>{
console.log(`receiving call from... ${call}`); // THIS NEVER TRIGGERS!
call.answer(stream)
call.on('stream',(otherUserVideoStream: MediaStream)=>{
console.log('receiving other user stream ' + otherUserVideoStream); // THIS NEVER RUNS
this.addOtherUserVideo(call.metadata.userId,otherUserVideoStream);
});
call.on('error',(err:any)=>{
console.log(err)
})
});
//------------------------------
// --- Connecting other user ---
//------------------------------
this.socket.on('user-connected',(userId:string)=>{
console.log('receiving user-connected event', 'Calling ' + userId); // THIS NEVER RUNS
setTimeout(()=>{ // Allow some time for new peers to connect
console.log("test3") // THIS NEVER RUNS
const call = myPeer.call(userId,stream,{
metadata:{userId:this.currentUserId},
});
call.on('stream',(otherUserVideoStream: MediaStream) =>{
console.log('receiving other stream after...') // THIS NEVER RUNS
this.addOtherUserVideo(userId,otherUserVideoStream)
});
call.on('close',()=>{
this.videos=this.videos.filter((video)=>video.userId!==userId);
});
},10000);
});
});
//------------------------------
// --- Disconnect other user ---
//------------------------------
this.socket.on('user-disconnected',(userId:string)=>{
console.log('receiving user-doscconected event from '+ userId) // THIS NEVER RUNS
this.videos = this.videos.filter((video)=>video.userId!==userId);
})
}
addMyVideo(stream:MediaStream){
console.log('added') // This works fine
this.videos.push({
muted:true,
srcObject:stream,
userId:this.currentUserId,
});
}
addOtherUserVideo(userId:string, stream:MediaStream){
console.log('second video added')
const alreadyExisting = this.videos.some(video => video.userId === userId)
if (alreadyExisting){
console.log(this.videos, userId);
return;
}
this.videos.push({
muted:false,
srcObject:stream,
userId,
})
}
onLoadedMetadata(event:Event){
(event.target as HTMLVideoElement).play()
}
}
I've also put the following script into the body of my index.html document:
<script src="http://localhost:3001/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost:3001');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
</script>
I'm importing Socket.Io into my app.module.ts file like this:
import{SocketIoModule} from 'ngx-socket-io';
//...
//...
imports: [
SocketIoModule.forRoot({
url:'http://localhost:3001',options: {}
})
]
I'm running my peerjs port with the following command:
peerjs --port 3001
My backend is running on port 3000 and my frontend on 4200, and they're working just fine.
NOTE: I've seen many other Stack Overflow posts on this topic, like these ones, but I've tried everything mentioned and none of them have worked for me:
peer.on('calll') is never being called
Peerjs call.on "stream" event isn't firing but peer.on "call" is