mirror of
https://github.com/fromchat-messenger/web.git
synced 2026-09-22 19:15:08 +03:00
Fix screenshare glitches
This commit is contained in:
@@ -238,20 +238,27 @@ async function createPeerConnection(userId: number): Promise<RTCPeerConnection>
|
||||
if (call && remoteStream) {
|
||||
const track = event.track;
|
||||
|
||||
// Apply E2EE transform to the receiver for this new track if session key is available
|
||||
// Apply E2EE transform to all tracks - video now uses header-preserving encryption
|
||||
if (call.sessionKey && window.RTCRtpScriptTransform) {
|
||||
try {
|
||||
const receiver = call.peerConnection.getReceivers().find(r => r.track === track);
|
||||
if (receiver && !call.transformedReceivers.has(receiver)) {
|
||||
const key = await importAesGcmKey(call.sessionKey);
|
||||
console.log(`Applying decrypt transform to newly received ${track.kind} track`);
|
||||
console.log(`Applying decrypt transform to newly received ${track.kind} track:`);
|
||||
console.log("- sessionId:", call.sessionId);
|
||||
console.log("- sessionKey (first 8 bytes):", Array.from(new Uint8Array(call.sessionKey).slice(0, 8)));
|
||||
// @ts-ignore
|
||||
receiver.transform = new RTCRtpScriptTransform(new E2EEWorker(), { key, mode: 'decrypt', sessionId: call.sessionId });
|
||||
call.transformedReceivers.add(receiver);
|
||||
console.log(`Decrypt transform applied successfully to ${track.kind} track`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to apply E2EE to received track:", error);
|
||||
}
|
||||
} else {
|
||||
console.log(`Skipping decrypt transform for ${track.kind} track - session key not available or RTCRtpScriptTransform not supported`);
|
||||
console.log("Session key exists:", !!call.sessionKey);
|
||||
console.log("RTCRtpScriptTransform available:", !!window.RTCRtpScriptTransform);
|
||||
}
|
||||
|
||||
// Determine stream type based on track kind and signaling state
|
||||
@@ -897,7 +904,7 @@ export async function toggleVideo(userId: number): Promise<boolean> {
|
||||
|
||||
// Add video track to peer connection
|
||||
const videoTrack = videoStream.getVideoTracks()[0];
|
||||
const sender = call.peerConnection.addTrack(videoTrack, videoStream);
|
||||
call.peerConnection.addTrack(videoTrack, videoStream);
|
||||
|
||||
console.log("Video track added successfully");
|
||||
console.log("Current senders:", call.peerConnection.getSenders().map(s => s.track?.kind));
|
||||
@@ -907,19 +914,21 @@ export async function toggleVideo(userId: number): Promise<boolean> {
|
||||
direction: t.direction
|
||||
})));
|
||||
|
||||
// Apply E2EE transform if session key exists and not already transformed
|
||||
if (call.sessionKey && window.RTCRtpScriptTransform && !call.transformedSenders.has(sender)) {
|
||||
// Apply E2EE transform with header-preserving encryption for video
|
||||
if (call.sessionKey && window.RTCRtpScriptTransform) {
|
||||
try {
|
||||
const key = await importAesGcmKey(call.sessionKey);
|
||||
console.log("Applying E2EE to video sender");
|
||||
sender.transform = new RTCRtpScriptTransform(new E2EEWorker(), { key, mode: "encrypt", sessionId: call.sessionId });
|
||||
call.transformedSenders.add(sender);
|
||||
console.log("Applying E2EE to video sender with header preservation");
|
||||
const sender = call.peerConnection.getSenders().find(s => s.track === videoTrack);
|
||||
if (sender && !call.transformedSenders.has(sender)) {
|
||||
sender.transform = new RTCRtpScriptTransform(new E2EEWorker(), { key, mode: "encrypt", sessionId: call.sessionId });
|
||||
call.transformedSenders.add(sender);
|
||||
console.log("E2EE applied to video sender successfully");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to apply E2EE to video:", error);
|
||||
throw error; // Fail securely
|
||||
}
|
||||
} else {
|
||||
console.log("Skipping E2EE for video - session key not available yet or already transformed");
|
||||
}
|
||||
|
||||
// Notify local video stream handler
|
||||
@@ -988,9 +997,12 @@ export async function toggleScreenShare(userId: number): Promise<boolean> {
|
||||
if (!call.isScreenSharing) {
|
||||
// Enable screen sharing
|
||||
try {
|
||||
// @ts-ignore - getDisplayMedia might not be in all TypeScript versions
|
||||
const screenStream = await navigator.mediaDevices.getDisplayMedia({
|
||||
video: true,
|
||||
video: {
|
||||
width: { ideal: 1920, max: 3840 },
|
||||
height: { ideal: 1080, max: 2160 },
|
||||
frameRate: { ideal: 60, max: 60 }
|
||||
},
|
||||
audio: false
|
||||
});
|
||||
|
||||
@@ -1017,32 +1029,9 @@ export async function toggleScreenShare(userId: number): Promise<boolean> {
|
||||
toggleScreenShare(userId);
|
||||
});
|
||||
|
||||
const sender = call.peerConnection.addTrack(videoTrack, screenStream);
|
||||
|
||||
console.log("Screen share track added successfully");
|
||||
|
||||
// Apply E2EE transform if session key exists and not already transformed
|
||||
if (call.sessionKey && window.RTCRtpScriptTransform && !call.transformedSenders.has(sender)) {
|
||||
try {
|
||||
const key = await importAesGcmKey(call.sessionKey);
|
||||
console.log("Applying E2EE to screen share sender");
|
||||
// @ts-ignore
|
||||
sender.transform = new RTCRtpScriptTransform(new E2EEWorker(), { key, mode: "encrypt", sessionId: call.sessionId });
|
||||
call.transformedSenders.add(sender);
|
||||
} catch (error) {
|
||||
console.error("Failed to apply E2EE to screen share:", error);
|
||||
throw error; // Fail securely
|
||||
}
|
||||
} else {
|
||||
console.log("Skipping E2EE for screen share - session key not available yet or already transformed");
|
||||
}
|
||||
|
||||
// Notify local screen share handler
|
||||
if (onLocalScreenShare) {
|
||||
onLocalScreenShare(userId, screenStream);
|
||||
}
|
||||
|
||||
// Send signaling message to notify remote peer
|
||||
// Send signaling message FIRST to notify remote peer before adding track
|
||||
// This ensures the receiver knows it's screen share before the track arrives
|
||||
console.log("Sending screen share toggle BEFORE adding track");
|
||||
await sendSignalingMessage({
|
||||
type: "call_screen_share_toggle",
|
||||
fromUserId: 0,
|
||||
@@ -1050,6 +1039,56 @@ export async function toggleScreenShare(userId: number): Promise<boolean> {
|
||||
data: { enabled: true }
|
||||
});
|
||||
|
||||
// Small delay to ensure signaling message is processed before track arrives
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
|
||||
call.peerConnection.addTrack(videoTrack, screenStream);
|
||||
|
||||
console.log("Screen share track added, immediately applying E2EE transform");
|
||||
|
||||
// CRITICAL: Apply E2EE transform IMMEDIATELY after track is added
|
||||
if (call.sessionKey && window.RTCRtpScriptTransform) {
|
||||
try {
|
||||
const key = await importAesGcmKey(call.sessionKey);
|
||||
console.log("Applying E2EE to screen share sender:");
|
||||
console.log("- sessionId:", call.sessionId);
|
||||
console.log("- sessionKey (first 8 bytes):", Array.from(new Uint8Array(call.sessionKey).slice(0, 8)));
|
||||
console.log("Available senders:", call.peerConnection.getSenders().map(s => ({
|
||||
track: s.track?.kind,
|
||||
id: s.track?.id
|
||||
})));
|
||||
console.log("Looking for screen share track:", videoTrack.id);
|
||||
|
||||
const sender = call.peerConnection.getSenders().find(s => s.track === videoTrack);
|
||||
console.log("Found screen share sender:", !!sender);
|
||||
|
||||
if (sender && !call.transformedSenders.has(sender)) {
|
||||
sender.transform = new RTCRtpScriptTransform(new E2EEWorker(), { key, mode: "encrypt", sessionId: call.sessionId });
|
||||
call.transformedSenders.add(sender);
|
||||
console.log("E2EE applied to screen share sender successfully");
|
||||
} else {
|
||||
console.log("Screen share sender not found or already transformed");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to apply E2EE to screen share:", error);
|
||||
throw error; // Fail securely
|
||||
}
|
||||
} else {
|
||||
console.log("Skipping E2EE for screen share - session key not available yet");
|
||||
console.log("Session key exists:", !!call.sessionKey);
|
||||
console.log("RTCRtpScriptTransform available:", !!window.RTCRtpScriptTransform);
|
||||
}
|
||||
|
||||
// Let browser handle screen share settings naturally
|
||||
// Avoid applying constraints that might cause glitches
|
||||
|
||||
// Notify local screen share handler
|
||||
if (onLocalScreenShare) {
|
||||
onLocalScreenShare(userId, screenStream);
|
||||
}
|
||||
|
||||
console.log("Screen share setup complete - using existing session key:", call.sessionId);
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("Failed to enable screen sharing:", error);
|
||||
|
||||
Reference in New Issue
Block a user