Enhance logging in SessionUsersPanel and ParticipantsPopup for debugging audio and video states. Update useWebRTC to initialize audio/video muted states from the service and add functionality to mute participants and disable their video. Adjust environment variables for server configuration.

This commit is contained in:
2025-11-05 17:47:39 +05:00
parent ddeb7d8148
commit d5b17d60c9
8 changed files with 457 additions and 22 deletions
+4 -4
View File
@@ -1,6 +1,6 @@
DATABASE_URL=postgres://postgres:v1sq3vD5faXL@194.26.138.94:5432/stream
JWT_SECRET=b5cf2bd3894fb24191f13dc9dddaeecccc92d0ee298e7ee41c2d0aab51c28fa1
# PORT=6000
# SOCKET_PORT=6001
PORT=3000
SOCKET_PORT=3001
PORT=6000
SOCKET_PORT=6001
# PORT=3000
# SOCKET_PORT=3001
+184 -1
View File
@@ -59,6 +59,8 @@ interface User {
id: string;
roomId?: string;
socketId: string;
isAudioEnabled?: boolean;
isVideoEnabled?: boolean;
}
const rooms = new Map<string, Room>();
@@ -119,17 +121,22 @@ io.on("connection", (socket) => {
const room = rooms.get(roomId)!;
room.participants.add(userId);
// Сохранить пользователя
// Сохранить пользователя с состоянием аудио/видео
users.set(userId, {
id: userId,
roomId,
socketId: socket.id,
isAudioEnabled: isAudioEnabled !== false,
isVideoEnabled: isVideoEnabled !== false,
});
console.log(
`[WebRTC] Room ${roomId} now has participants:`,
Array.from(room.participants)
);
console.log(
`[WebRTC] User ${userId} media state: audio=${isAudioEnabled !== false}, video=${isVideoEnabled !== false}`
);
// Уведомить других участников
socket.to(roomId).emit("user-joined", userId);
@@ -154,6 +161,24 @@ io.on("connection", (socket) => {
participants
);
socket.emit("room-participants", participants);
// Отправить состояние аудио/видео существующих участников новому пользователю
participants.forEach((participantId) => {
const participant = users.get(participantId);
if (participant) {
console.log(
`[WebRTC] Sending ${participantId} media state to ${userId}: audio=${participant.isAudioEnabled}, video=${participant.isVideoEnabled}`
);
socket.emit("audio-toggle", {
userId: participantId,
isEnabled: participant.isAudioEnabled !== false,
});
socket.emit("video-toggle", {
userId: participantId,
isEnabled: participant.isVideoEnabled !== false,
});
}
});
}
);
@@ -225,6 +250,14 @@ io.on("connection", (socket) => {
console.log(
`[WebRTC] Audio toggle from ${userId} in room ${roomId}: ${isEnabled}`
);
// Обновляем сохраненное состояние пользователя
const user = users.get(userId);
if (user) {
user.isAudioEnabled = isEnabled;
console.log(`[WebRTC] Updated ${userId} audio state to ${isEnabled}`);
}
// Отправляем всем в комнате (кроме отправителя)
socket.to(roomId).emit("audio-toggle", { userId, isEnabled });
});
@@ -233,6 +266,14 @@ io.on("connection", (socket) => {
console.log(
`[WebRTC] Video toggle from ${userId} in room ${roomId}: ${isEnabled}`
);
// Обновляем сохраненное состояние пользователя
const user = users.get(userId);
if (user) {
user.isVideoEnabled = isEnabled;
console.log(`[WebRTC] Updated ${userId} video state to ${isEnabled}`);
}
// Отправляем всем в комнате (кроме отправителя)
socket.to(roomId).emit("video-toggle", { userId, isEnabled });
});
@@ -243,6 +284,148 @@ io.on("connection", (socket) => {
socket.to(roomId).emit("speaking-state", { userId, isSpeaking });
});
// Обработка команды выключения микрофона участника
socket.on("mute-participant", async ({ roomId, targetUserId }) => {
console.log(
`[WebRTC] Mute participant request: ${targetUserId} in room ${roomId}`
);
// Получаем информацию о пользователе, который отправил команду
const requestingUser = findUserBySocketId(socket.id);
if (!requestingUser) {
console.warn(`[WebRTC] Unauthorized mute request from unknown socket ${socket.id}`);
socket.emit("error", { message: "Unauthorized: user not found" });
return;
}
// Проверяем, что пользователь находится в той же комнате
if (requestingUser.roomId !== roomId) {
console.warn(
`[WebRTC] User ${requestingUser.id} tried to mute participant in room ${roomId}, but is in room ${requestingUser.roomId}`
);
socket.emit("error", { message: "Unauthorized: not in the same room" });
return;
}
// Проверяем, что пользователь является организатором сессии
try {
const session = await serverSessionService.findById(roomId);
if (!session) {
console.warn(`[WebRTC] Session ${roomId} not found`);
socket.emit("error", { message: "Session not found" });
return;
}
// Проверяем, что запрашивающий пользователь - организатор
// Организатор - это userId (для авторизованных) или guestId (для гостей)
const isOrganizer =
(session.userId && session.userId === requestingUser.id) ||
(session.guestId && session.guestId === requestingUser.id);
if (!isOrganizer) {
console.warn(
`[WebRTC] User ${requestingUser.id} is not the organizer of session ${roomId}`
);
socket.emit("error", { message: "Unauthorized: only organizer can mute participants" });
return;
}
console.log(`[WebRTC] User ${requestingUser.id} is authorized as organizer`);
} catch (error) {
console.error(`[WebRTC] Error checking session organizer:`, error);
socket.emit("error", { message: "Failed to verify permissions" });
return;
}
// Обновляем состояние участника
const targetUser = users.get(targetUserId);
if (targetUser) {
targetUser.isAudioEnabled = false;
console.log(`[WebRTC] Updated ${targetUserId} audio state to false`);
}
// Отправляем команду конкретному участнику
const targetSocketId = findSocketIdByUserId(targetUserId);
if (targetSocketId) {
io.to(targetSocketId).emit("force-mute-audio");
console.log(`[WebRTC] Sent force-mute-audio to ${targetUserId}`);
}
// Уведомляем всех в комнате об изменении состояния
io.to(roomId).emit("audio-toggle", { userId: targetUserId, isEnabled: false });
});
// Обработка команды выключения камеры участника
socket.on("disable-participant-video", async ({ roomId, targetUserId }) => {
console.log(
`[WebRTC] Disable video request: ${targetUserId} in room ${roomId}`
);
// Получаем информацию о пользователе, который отправил команду
const requestingUser = findUserBySocketId(socket.id);
if (!requestingUser) {
console.warn(`[WebRTC] Unauthorized disable video request from unknown socket ${socket.id}`);
socket.emit("error", { message: "Unauthorized: user not found" });
return;
}
// Проверяем, что пользователь находится в той же комнате
if (requestingUser.roomId !== roomId) {
console.warn(
`[WebRTC] User ${requestingUser.id} tried to disable video in room ${roomId}, but is in room ${requestingUser.roomId}`
);
socket.emit("error", { message: "Unauthorized: not in the same room" });
return;
}
// Проверяем, что пользователь является организатором сессии
try {
const session = await serverSessionService.findById(roomId);
if (!session) {
console.warn(`[WebRTC] Session ${roomId} not found`);
socket.emit("error", { message: "Session not found" });
return;
}
// Проверяем, что запрашивающий пользователь - организатор
// Организатор - это userId (для авторизованных) или guestId (для гостей)
const isOrganizer =
(session.userId && session.userId === requestingUser.id) ||
(session.guestId && session.guestId === requestingUser.id);
if (!isOrganizer) {
console.warn(
`[WebRTC] User ${requestingUser.id} is not the organizer of session ${roomId}`
);
socket.emit("error", { message: "Unauthorized: only organizer can disable video" });
return;
}
console.log(`[WebRTC] User ${requestingUser.id} is authorized as organizer`);
} catch (error) {
console.error(`[WebRTC] Error checking session organizer:`, error);
socket.emit("error", { message: "Failed to verify permissions" });
return;
}
// Обновляем состояние участника
const targetUser = users.get(targetUserId);
if (targetUser) {
targetUser.isVideoEnabled = false;
console.log(`[WebRTC] Updated ${targetUserId} video state to false`);
}
// Отправляем команду конкретному участнику
const targetSocketId = findSocketIdByUserId(targetUserId);
if (targetSocketId) {
io.to(targetSocketId).emit("force-disable-video");
console.log(`[WebRTC] Sent force-disable-video to ${targetUserId}`);
}
// Уведомляем всех в комнате об изменении состояния
io.to(roomId).emit("video-toggle", { userId: targetUserId, isEnabled: false });
});
// Обработка сообщений чата
socket.on(
"chat-message",