makinuh commited on
Commit
484723b
·
verified ·
1 Parent(s): 6f26d39

Create server.py

Browse files
Files changed (1) hide show
  1. server.py +126 -0
server.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # server.py (using FastAPI and FastRTC)
2
+ import asyncio
3
+ import json
4
+ import uuid
5
+
6
+ from fastapi import FastAPI, WebSocket, WebSocketDisconnect
7
+ from fastrtc import RTCRoom, RTCRoomManager
8
+
9
+ app = FastAPI()
10
+ room_manager = RTCRoomManager()
11
+
12
+ @app.websocket("/ws/{room_id}/{client_id}")
13
+ async def websocket_endpoint(websocket: WebSocket, room_id: str, client_id: str):
14
+ await websocket.accept()
15
+ room = room_manager.get_or_create_room(room_id)
16
+ peer = await room.join(client_id, websocket)
17
+
18
+ try:
19
+ while True:
20
+ message = await websocket.receive_text()
21
+ data = json.loads(message)
22
+ if data["type"] == "offer" or data["type"] == "answer" or data["type"] == "candidate":
23
+ await peer.handle_sdp(data)
24
+ else:
25
+ print(f"Received unknown message: {data}")
26
+
27
+ except WebSocketDisconnect:
28
+ await room.leave(client_id)
29
+ print(f"Client {client_id} disconnected from room {room_id}")
30
+
31
+ # client.js (modified JavaScript)
32
+ const localVideo = document.getElementById('localVideo');
33
+ const remoteVideo = document.getElementById('remoteVideo');
34
+ const callBtn = document.getElementById('callBtn');
35
+ const endCallBtn = document.getElementById('endCallBtn');
36
+ // ... other DOM elements
37
+
38
+ let peerConnection;
39
+ let localStream;
40
+ let socket;
41
+ let roomId;
42
+ let clientId;
43
+
44
+ async function init() {
45
+ try {
46
+ localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
47
+ localVideo.srcObject = localStream;
48
+ roomId = uuid.v4(); // Generate a unique room ID
49
+ clientId = uuid.v4(); // Generate a unique client ID
50
+ socket = new WebSocket(`ws://localhost:8000/ws/${roomId}/${clientId}`); // Connect to the WebSocket server
51
+ socket.onmessage = handleSocketMessage;
52
+ socket.onopen = startCall; // Start call after socket opens.
53
+ setupEventListeners();
54
+ optimizerPanel.classList.remove('hidden');
55
+ applyBandwidthPreset(currentBandwidthPreset);
56
+ } catch (error) {
57
+ console.error('Initialization error:', error);
58
+ }
59
+ }
60
+
61
+ async function startCall() {
62
+ if (!localStream) {
63
+ alert('Please allow camera and microphone access first.');
64
+ return;
65
+ }
66
+
67
+ connectionModal.classList.remove('hidden');
68
+ simulateConnectionProgress();
69
+
70
+ try {
71
+ peerConnection = new RTCPeerConnection({
72
+ iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
73
+ });
74
+
75
+ peerConnection.onicecandidate = handleICECandidate;
76
+ peerConnection.ontrack = handleTrack;
77
+
78
+ localStream.getTracks().forEach(track => peerConnection.addTrack(track, localStream));
79
+
80
+ const offer = await peerConnection.createOffer();
81
+ await peerConnection.setLocalDescription(offer);
82
+
83
+ socket.send(JSON.stringify({ type: 'offer', sdp: offer.sdp })); // Send the offer via WebSocket
84
+
85
+ } catch (error) {
86
+ console.error('Error starting call:', error);
87
+ connectionModal.classList.add('hidden');
88
+ alert('Failed to start call. Please try again.');
89
+ }
90
+ }
91
+
92
+ function handleSocketMessage(event) {
93
+ const data = JSON.parse(event.data);
94
+
95
+ if (data.type === 'offer' || data.type === 'answer') {
96
+ peerConnection.setRemoteDescription(new RTCSessionDescription(data));
97
+ if (data.type === 'offer') {
98
+ peerConnection.createAnswer()
99
+ .then(answer => peerConnection.setLocalDescription(answer))
100
+ .then(() => socket.send(JSON.stringify({ type: 'answer', sdp: peerConnection.localDescription.sdp })));
101
+ }
102
+ } else if (data.type === 'candidate') {
103
+ peerConnection.addIceCandidate(new RTCIceCandidate(data.candidate));
104
+ }
105
+ // ... rest of the socket message handling
106
+ }
107
+
108
+ function handleICECandidate(event) {
109
+ if (event.candidate) {
110
+ socket.send(JSON.stringify({ type: 'candidate', candidate: event.candidate })); // Send ICE candidate via WebSocket
111
+ }
112
+ }
113
+
114
+ function handleTrack(event) {
115
+ remoteVideo.srcObject = event.streams[0];
116
+ connectionStatus.textContent = 'Connected';
117
+ connectionStatus.className = 'font-medium text-green-400';
118
+ bandwidthIndicator.classList.remove('hidden');
119
+ updateBandwidthDisplay();
120
+ callBtn.classList.add('hidden');
121
+ endCallBtn.classList.remove('hidden');
122
+ connectionModal.classList.add('hidden');
123
+ isCallActive = true;
124
+ }
125
+
126
+ // ... rest of the JavaScript code (toggleVideo, toggleAudio, etc.)