todo comment fix screen sharing and video aspect ratio

This commit is contained in:
srtk 2026-02-08 16:53:06 +05:30
parent 9eb33512f4
commit 2a9e80cc5a
10 changed files with 902 additions and 188 deletions

View file

@ -82,6 +82,12 @@ app.whenReady().then(() => {
}
});
ipcMain.on('send-screen-frame', (_, { frame }) => {
if (networkManager) {
networkManager.sendScreenFrame(frame);
}
});
// Screen sharing: get available sources
ipcMain.handle('get-screen-sources', async () => {
const sources = await desktopCapturer.getSources({
@ -95,6 +101,13 @@ app.whenReady().then(() => {
}));
});
// Chat
ipcMain.handle('send-chat', (_, { message, displayName }) => {
if (networkManager) {
networkManager.sendChat(message, displayName);
}
});
createWindow()
app.on('activate', function () {

View file

@ -79,16 +79,18 @@ export class NetworkManager extends EventEmitter {
switch (msg.type) {
case 'Joined':
console.log('Joined Room:', msg.data);
this.userId = msg.data.self_id; // Server sends self_id, not user_id
// Init UDP
this.userId = msg.data.self_id;
this.setupUdp();
resolve(msg.data); // Return joined data (peers, etc)
resolve(msg.data);
break;
case 'PeerJoined':
this.mainWindow.webContents.send('peer-joined', msg.data);
this.safeSend('peer-joined', msg.data);
break;
case 'PeerLeft':
this.mainWindow.webContents.send('peer-left', msg.data);
this.safeSend('peer-left', msg.data);
break;
case 'ChatMessage':
this.safeSend('chat-message', msg.data);
break;
case 'Error':
console.error('WS Error Msg:', msg.data);
@ -97,6 +99,20 @@ export class NetworkManager extends EventEmitter {
}
}
sendChat(message: string, displayName: string) {
if (!this.ws) return;
const chatMsg = {
type: 'ChatMessage',
data: {
user_id: this.userId,
display_name: displayName,
message,
timestamp: Date.now()
}
};
this.ws.send(JSON.stringify(chatMsg));
}
setupUdp() {
this.udp = dgram.createSocket('udp4');
@ -128,6 +144,10 @@ export class NetworkManager extends EventEmitter {
// const flags = msg.readUInt16LE(20);
const payload = msg.subarray(HEADER_SIZE);
const sequence = msg.readUInt32LE(6);
const timestamp = Number(msg.readBigUInt64LE(10));
const fragIdx = msg.readUInt8(18);
const fragCnt = msg.readUInt8(19);
if (mediaType === MediaType.Audio) {
// Forward audio? Or decode here?
@ -137,35 +157,69 @@ export class NetworkManager extends EventEmitter {
// OR decode here with `opus-native` binding.
// For now, let's send payload to renderer via IPC.
// Note: IPC with high frequency audio packets might be laggy.
// But for MVP it's okay.
this.mainWindow.webContents.send('audio-frame', { user_id: userId, data: payload });
this.safeSend('audio-frame', { user_id: userId, data: payload });
} else if (mediaType === MediaType.Video) {
// Send to renderer
this.mainWindow.webContents.send('video-frame', { user_id: userId, data: payload });
this.safeSend('video-frame', {
user_id: userId,
data: payload,
seq: sequence,
ts: timestamp,
fidx: fragIdx,
fcnt: fragCnt
});
} else if (mediaType === MediaType.Screen) {
this.safeSend('screen-frame', {
user_id: userId,
data: payload,
seq: sequence,
ts: timestamp,
fidx: fragIdx,
fcnt: fragCnt
});
}
}
private safeSend(channel: string, data: any) {
if (this.mainWindow && !this.mainWindow.isDestroyed() && this.mainWindow.webContents) {
try {
this.mainWindow.webContents.send(channel, data);
} catch (e) {
console.error(`Failed to send ${channel} to renderer:`, e);
}
}
}
sendVideoFrame(frame: Uint8Array) {
if (!this.udp) return;
if (!this.udp || !this.userId) return;
// Construct Header
const header = Buffer.alloc(HEADER_SIZE);
header.writeUInt8(1, 0); // Version
header.writeUInt8(MediaType.Video, 1);
header.writeUInt32LE(this.userId, 2);
header.writeUInt32LE(this.videoSeq++, 6);
header.writeBigUInt64LE(BigInt(Date.now()), 10);
header.writeUInt8(0, 18); // Frag idx
header.writeUInt8(1, 19); // Frag cnt
header.writeUInt16LE(0, 20); // Flags
const buffer = Buffer.from(frame);
const MAX_PAYLOAD = 1400;
const fragCount = Math.ceil(buffer.length / MAX_PAYLOAD);
const seq = this.videoSeq++;
const ts = BigInt(Date.now());
const packet = Buffer.concat([header, Buffer.from(frame)]);
for (let i = 0; i < fragCount; i++) {
const start = i * MAX_PAYLOAD;
const end = Math.min(start + MAX_PAYLOAD, buffer.length);
const chunk = buffer.subarray(start, end);
console.log(`[UDP] Sending Video: ${packet.length} bytes to ${SERVER_UDP_HOST}:${SERVER_UDP_PORT}`);
// Send
this.udp.send(packet, SERVER_UDP_PORT, SERVER_UDP_HOST, (err) => {
if (err) console.error('UDP Send Error', err);
});
// MediaType.Video = 1
const header = Buffer.alloc(HEADER_SIZE);
header.writeUInt8(1, 0); // Version
header.writeUInt8(MediaType.Video, 1);
header.writeUInt32LE(this.userId, 2);
header.writeUInt32LE(seq, 6);
header.writeBigUInt64LE(ts, 10);
header.writeUInt8(i, 18); // Frag idx
header.writeUInt8(fragCount, 19); // Frag cnt
header.writeUInt16LE(0, 20); // Flags
const packet = Buffer.concat([header, chunk]);
this.udp.send(packet, SERVER_UDP_PORT, SERVER_UDP_HOST, (err) => {
if (err) console.error('UDP Video Send Error', err);
});
}
}
sendAudioFrame(frame: Uint8Array) {
@ -184,12 +238,46 @@ export class NetworkManager extends EventEmitter {
const packet = Buffer.concat([header, Buffer.from(frame)]);
console.log(`[UDP] Sending Audio: ${packet.length} bytes to ${SERVER_UDP_HOST}:${SERVER_UDP_PORT}`);
this.udp.send(packet, SERVER_UDP_PORT, SERVER_UDP_HOST, (err) => {
if (err) console.error('UDP Audio Send Error', err);
});
}
private screenSeq = 0;
sendScreenFrame(frame: number[]) {
if (!this.udp || !this.userId) return;
const buffer = Buffer.from(frame);
const MAX_PAYLOAD = 1400; // MTU friendly (~1500 total with headers)
const fragCount = Math.ceil(buffer.length / MAX_PAYLOAD);
const seq = this.screenSeq++;
const ts = BigInt(Date.now());
for (let i = 0; i < fragCount; i++) {
const start = i * MAX_PAYLOAD;
const end = Math.min(start + MAX_PAYLOAD, buffer.length);
const chunk = buffer.subarray(start, end);
// MediaType.Screen = 2
const header = Buffer.alloc(HEADER_SIZE);
header.writeUInt8(1, 0); // Version
header.writeUInt8(MediaType.Screen, 1);
header.writeUInt32LE(this.userId, 2);
header.writeUInt32LE(seq, 6);
header.writeBigUInt64LE(ts, 10);
header.writeUInt8(i, 18); // Frag idx
header.writeUInt8(fragCount, 19); // Frag cnt
header.writeUInt16LE(0, 20); // Flags
const packet = Buffer.concat([header, chunk]);
this.udp.send(packet, SERVER_UDP_PORT, SERVER_UDP_HOST, (err) => {
if (err) console.error('UDP Screen Send Error', err);
});
}
}
sendHandshake() {
if (!this.udp || !this.userId || !this.roomCode) {
console.error('[UDP] Cannot send handshake: missing udp, userId, or roomCode');