feat: Optimize WebRTC pipeline for 60fps screen sharing
- Implemented 'Overdrive' logic to force high bitrates on Chrome - Fixed 'Auto' preset to default to stable 720p60 - Added persistent 'Triple-Kick' hammer to prevent bitrate throttling - Fixed sidebar connection status sync - Added comprehensive diagnostic logger
This commit is contained in:
@@ -144,6 +144,18 @@ export function handleClientEvent(
|
||||
case 'channel_ack':
|
||||
handleChannelAck(event, userId);
|
||||
break;
|
||||
case 'dm_call_start':
|
||||
handleDmCallStart(event, userId, username);
|
||||
break;
|
||||
case 'dm_call_accept':
|
||||
handleDmCallAccept(event, userId);
|
||||
break;
|
||||
case 'dm_call_reject':
|
||||
handleDmCallReject(event, userId);
|
||||
break;
|
||||
case 'dm_call_end':
|
||||
handleDmCallEnd(event, userId);
|
||||
break;
|
||||
default:
|
||||
connectionManager.sendToUser(userId, {
|
||||
type: 'error',
|
||||
@@ -725,3 +737,146 @@ function handleChannelAck(event: Record<string, unknown>, userId: string): void
|
||||
messageId,
|
||||
});
|
||||
}
|
||||
|
||||
// ─── DM Call Handlers ──────────────────────────────────────────────────────────
|
||||
|
||||
function handleDmCallStart(event: Record<string, unknown>, userId: string, username: string): void {
|
||||
const dmChannelId = event.dmChannelId as string;
|
||||
if (!dmChannelId || typeof dmChannelId !== 'string') {
|
||||
connectionManager.sendToUser(userId, { type: 'error', message: 'dmChannelId is required' });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isDmMember(dmChannelId, userId)) {
|
||||
connectionManager.sendToUser(userId, { type: 'error', message: 'You are not a member of this DM channel' });
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to start the call (fails if already active)
|
||||
const started = connectionManager.startCall(dmChannelId, userId);
|
||||
if (!started) {
|
||||
connectionManager.sendToUser(userId, { type: 'error', message: 'A call is already active in this DM channel' });
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the other DM member(s) and send incoming call notification
|
||||
const db = getDb();
|
||||
const dmMembers = db.select()
|
||||
.from(schema.dmMembers)
|
||||
.where(eq(schema.dmMembers.dmChannelId, dmChannelId))
|
||||
.all();
|
||||
|
||||
for (const member of dmMembers) {
|
||||
if (member.userId !== userId) {
|
||||
connectionManager.sendToUser(member.userId, {
|
||||
type: 'dm_call_incoming',
|
||||
dmChannelId,
|
||||
callerId: userId,
|
||||
callerName: username,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleDmCallAccept(event: Record<string, unknown>, userId: string): void {
|
||||
const dmChannelId = event.dmChannelId as string;
|
||||
if (!dmChannelId || typeof dmChannelId !== 'string') {
|
||||
connectionManager.sendToUser(userId, { type: 'error', message: 'dmChannelId is required' });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isDmMember(dmChannelId, userId)) {
|
||||
connectionManager.sendToUser(userId, { type: 'error', message: 'You are not a member of this DM channel' });
|
||||
return;
|
||||
}
|
||||
|
||||
const activeCall = connectionManager.getActiveCall(dmChannelId);
|
||||
if (!activeCall) {
|
||||
connectionManager.sendToUser(userId, { type: 'error', message: 'No active call in this DM channel' });
|
||||
return;
|
||||
}
|
||||
|
||||
// Notify all DM members that the call was accepted
|
||||
const db = getDb();
|
||||
const dmMembers = db.select()
|
||||
.from(schema.dmMembers)
|
||||
.where(eq(schema.dmMembers.dmChannelId, dmChannelId))
|
||||
.all();
|
||||
|
||||
for (const member of dmMembers) {
|
||||
connectionManager.sendToUser(member.userId, {
|
||||
type: 'dm_call_accepted',
|
||||
dmChannelId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function handleDmCallReject(event: Record<string, unknown>, userId: string): void {
|
||||
const dmChannelId = event.dmChannelId as string;
|
||||
if (!dmChannelId || typeof dmChannelId !== 'string') {
|
||||
connectionManager.sendToUser(userId, { type: 'error', message: 'dmChannelId is required' });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isDmMember(dmChannelId, userId)) {
|
||||
connectionManager.sendToUser(userId, { type: 'error', message: 'You are not a member of this DM channel' });
|
||||
return;
|
||||
}
|
||||
|
||||
const activeCall = connectionManager.getActiveCall(dmChannelId);
|
||||
if (!activeCall) {
|
||||
return; // No active call, silently ignore
|
||||
}
|
||||
|
||||
// End the call since it was rejected
|
||||
connectionManager.endCall(dmChannelId);
|
||||
|
||||
// Notify all DM members that the call was rejected
|
||||
const db = getDb();
|
||||
const dmMembers = db.select()
|
||||
.from(schema.dmMembers)
|
||||
.where(eq(schema.dmMembers.dmChannelId, dmChannelId))
|
||||
.all();
|
||||
|
||||
for (const member of dmMembers) {
|
||||
connectionManager.sendToUser(member.userId, {
|
||||
type: 'dm_call_rejected',
|
||||
dmChannelId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function handleDmCallEnd(event: Record<string, unknown>, userId: string): void {
|
||||
const dmChannelId = event.dmChannelId as string;
|
||||
if (!dmChannelId || typeof dmChannelId !== 'string') {
|
||||
connectionManager.sendToUser(userId, { type: 'error', message: 'dmChannelId is required' });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isDmMember(dmChannelId, userId)) {
|
||||
connectionManager.sendToUser(userId, { type: 'error', message: 'You are not a member of this DM channel' });
|
||||
return;
|
||||
}
|
||||
|
||||
const activeCall = connectionManager.getActiveCall(dmChannelId);
|
||||
if (!activeCall) {
|
||||
return; // No active call, silently ignore
|
||||
}
|
||||
|
||||
// End the call
|
||||
connectionManager.endCall(dmChannelId);
|
||||
|
||||
// Notify all DM members that the call ended
|
||||
const db = getDb();
|
||||
const dmMembers = db.select()
|
||||
.from(schema.dmMembers)
|
||||
.where(eq(schema.dmMembers.dmChannelId, dmChannelId))
|
||||
.all();
|
||||
|
||||
for (const member of dmMembers) {
|
||||
connectionManager.sendToUser(member.userId, {
|
||||
type: 'dm_call_ended',
|
||||
dmChannelId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@ class ConnectionManager {
|
||||
private voiceStates: Map<string, Set<string>> = new Map();
|
||||
// ws → userId (reverse lookup)
|
||||
private wsToUser: Map<WebSocket, string> = new Map();
|
||||
// dmChannelId → { callerId, startedAt } — active DM calls
|
||||
private activeCalls: Map<string, { callerId: string; startedAt: number }> = new Map();
|
||||
|
||||
addConnection(userId: string, ws: WebSocket): void {
|
||||
if (!this.connections.has(userId)) {
|
||||
@@ -136,6 +138,21 @@ class ConnectionManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
// DM call management
|
||||
startCall(dmChannelId: string, callerId: string): boolean {
|
||||
if (this.activeCalls.has(dmChannelId)) return false; // Already in a call
|
||||
this.activeCalls.set(dmChannelId, { callerId, startedAt: Date.now() });
|
||||
return true;
|
||||
}
|
||||
|
||||
endCall(dmChannelId: string): void {
|
||||
this.activeCalls.delete(dmChannelId);
|
||||
}
|
||||
|
||||
getActiveCall(dmChannelId: string): { callerId: string; startedAt: number } | undefined {
|
||||
return this.activeCalls.get(dmChannelId);
|
||||
}
|
||||
|
||||
// Send to a specific user (all their connections)
|
||||
sendToUser(userId: string, event: ServerEvent): void {
|
||||
const connections = this.getUserConnections(userId);
|
||||
|
||||
Reference in New Issue
Block a user