log优化
This commit is contained in:
@@ -1,3 +1,6 @@
|
|||||||
|
import { createLogger } from './logger.js';
|
||||||
|
|
||||||
|
const logger = createLogger('chat');
|
||||||
/**
|
/**
|
||||||
* 消息模块
|
* 消息模块
|
||||||
* 处理聊天消息的发送、接收和显示
|
* 处理聊天消息的发送、接收和显示
|
||||||
@@ -72,7 +75,7 @@ function sendChatMessage(message) {
|
|||||||
* @param {Object} data - 消息数据
|
* @param {Object} data - 消息数据
|
||||||
*/
|
*/
|
||||||
function handleChatMessage(data) {
|
function handleChatMessage(data) {
|
||||||
console.log('处理聊天:', data);
|
logger.debug('处理聊天:', data);
|
||||||
addMessage(data);
|
addMessage(data);
|
||||||
|
|
||||||
const isImage = data.content && data.content.startsWith('data:image/');
|
const isImage = data.content && data.content.startsWith('data:image/');
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
import { createLogger } from '../logger.js';
|
||||||
|
|
||||||
|
const logger = createLogger('legacy-connect');
|
||||||
/**
|
/**
|
||||||
* 连接界面逻辑
|
* 连接界面逻辑
|
||||||
* 处理初始连接、创建通话和加入通话的功能
|
* 处理初始连接、创建通话和加入通话的功能
|
||||||
@@ -51,7 +54,7 @@ async function getAllConnectionIds() {
|
|||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
displayConnectionIds(data.connectionIds);
|
displayConnectionIds(data.connectionIds);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching connection IDs:', error);
|
logger.error('Error fetching connection IDs:', error);
|
||||||
showNotification('获取连接ID失败', 'error');
|
showNotification('获取连接ID失败', 'error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -164,7 +167,7 @@ function loadUserSettings() {
|
|||||||
document.getElementById('userAvatar').src = avatar;
|
document.getElementById('userAvatar').src = avatar;
|
||||||
document.getElementById('avatarPreview').src = avatar;
|
document.getElementById('avatarPreview').src = avatar;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading user settings:', error);
|
logger.error('Error loading user settings:', error);
|
||||||
// 加载失败时使用默认头像
|
// 加载失败时使用默认头像
|
||||||
const defaultAvatar = '/images/p1.png';
|
const defaultAvatar = '/images/p1.png';
|
||||||
document.getElementById('userAvatar').src = defaultAvatar;
|
document.getElementById('userAvatar').src = defaultAvatar;
|
||||||
@@ -254,7 +257,7 @@ function handleAvatarUpload(event) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.error('Error uploading avatar:', error);
|
logger.error('Error uploading avatar:', error);
|
||||||
showNotification('头像上传失败,请重试', 'error');
|
showNotification('头像上传失败,请重试', 'error');
|
||||||
|
|
||||||
// 上传失败时,使用默认头像
|
// 上传失败时,使用默认头像
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ import {
|
|||||||
renderOnlineUsers
|
renderOnlineUsers
|
||||||
} from './connect-directory.js';
|
} from './connect-directory.js';
|
||||||
import { createProfileSettingsController } from './profile-settings.js';
|
import { createProfileSettingsController } from './profile-settings.js';
|
||||||
|
import { createLogger } from './logger.js';
|
||||||
|
|
||||||
|
const logger = createLogger('connectview');
|
||||||
|
|
||||||
let onWsStatusChange = null;
|
let onWsStatusChange = null;
|
||||||
let cachedOnlineUsers = [];
|
let cachedOnlineUsers = [];
|
||||||
@@ -45,9 +48,9 @@ export async function initWebSocket() {
|
|||||||
store.syncSocketUserInfo();
|
store.syncSocketUserInfo();
|
||||||
updateWsStatus(true);
|
updateWsStatus(true);
|
||||||
await refreshOnlineUsers();
|
await refreshOnlineUsers();
|
||||||
console.log('WebSocket initialized from connectview');
|
logger.debug('WebSocket initialized from connectview');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to initialize WebSocket:', error);
|
logger.error('Failed to initialize WebSocket:', error);
|
||||||
updateWsStatus(false);
|
updateWsStatus(false);
|
||||||
showNotification('WebSocket连接失败,请刷新页面重试', 'error');
|
showNotification('WebSocket连接失败,请刷新页面重试', 'error');
|
||||||
}
|
}
|
||||||
@@ -62,7 +65,7 @@ async function refreshOnlineUsers(silent = true) {
|
|||||||
showNotification(`当前共有 ${cachedOnlineUsers.length} 个WebSocket用户在线`);
|
showNotification(`当前共有 ${cachedOnlineUsers.length} 个WebSocket用户在线`);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching online users:', error);
|
logger.error('Error fetching online users:', error);
|
||||||
if (!silent) {
|
if (!silent) {
|
||||||
showNotification('获取在线用户失败', 'error');
|
showNotification('获取在线用户失败', 'error');
|
||||||
}
|
}
|
||||||
@@ -78,7 +81,7 @@ async function getAllConnectionIds() {
|
|||||||
updateConnectionIdList(connectionIds);
|
updateConnectionIdList(connectionIds);
|
||||||
updateOnlineUsersList(cachedOnlineUsers);
|
updateOnlineUsersList(cachedOnlineUsers);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching connection IDs:', error);
|
logger.error('Error fetching connection IDs:', error);
|
||||||
showNotification('获取连接信息失败', 'error');
|
showNotification('获取连接信息失败', 'error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,7 +107,7 @@ function getCurrentUserId() {
|
|||||||
const settings = JSON.parse(localStorage.getItem('userSettings') || '{}');
|
const settings = JSON.parse(localStorage.getItem('userSettings') || '{}');
|
||||||
return settings.userId || settings.id || '';
|
return settings.userId || settings.id || '';
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error parsing current user settings:', error);
|
logger.error('Error parsing current user settings:', error);
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
import { createLogger } from './logger.js';
|
||||||
|
|
||||||
|
const logger = createLogger('invite');
|
||||||
const DEFAULT_CALLER_NAME = '\u9080\u8bf7\u65b9';
|
const DEFAULT_CALLER_NAME = '\u9080\u8bf7\u65b9';
|
||||||
const DEFAULT_CALLER_AVATAR = '/images/p2.png';
|
const DEFAULT_CALLER_AVATAR = '/images/p2.png';
|
||||||
const DEFAULT_APPLY_REASON = '\u672a\u586b\u5199';
|
const DEFAULT_APPLY_REASON = '\u672a\u586b\u5199';
|
||||||
@@ -127,7 +130,7 @@ export function createInviteController({
|
|||||||
targetUserId: pendingInvite.inviterUserId
|
targetUserId: pendingInvite.inviterUserId
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error accepting invite:', error);
|
logger.error('Error accepting invite:', error);
|
||||||
notify('\u63a5\u53d7\u9080\u8bf7\u5931\u8d25\uff0c\u8bf7\u7a0d\u540e\u91cd\u8bd5', 'error');
|
notify('\u63a5\u53d7\u9080\u8bf7\u5931\u8d25\uff0c\u8bf7\u7a0d\u540e\u91cd\u8bd5', 'error');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -152,7 +155,7 @@ export function createInviteController({
|
|||||||
targetUserId: pendingInvite.inviterUserId
|
targetUserId: pendingInvite.inviterUserId
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error rejecting invite:', error);
|
logger.error('Error rejecting invite:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
84
client/public/logger.js
Normal file
84
client/public/logger.js
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
const LOG_LEVELS = {
|
||||||
|
debug: 10,
|
||||||
|
info: 20,
|
||||||
|
warn: 30,
|
||||||
|
error: 40,
|
||||||
|
silent: 50
|
||||||
|
};
|
||||||
|
|
||||||
|
const STORAGE_KEY = 'video_socket_log_level';
|
||||||
|
const DEFAULT_LEVEL = 'warn';
|
||||||
|
|
||||||
|
function normalizeLevel(level) {
|
||||||
|
if (!level) {
|
||||||
|
return DEFAULT_LEVEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalized = String(level).toLowerCase();
|
||||||
|
return Object.prototype.hasOwnProperty.call(LOG_LEVELS, normalized)
|
||||||
|
? normalized
|
||||||
|
: DEFAULT_LEVEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getConfiguredLevel() {
|
||||||
|
try {
|
||||||
|
const queryLevel = new URLSearchParams(window.location.search).get('logLevel');
|
||||||
|
if (queryLevel) {
|
||||||
|
return normalizeLevel(queryLevel);
|
||||||
|
}
|
||||||
|
} catch (_error) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const storageLevel = localStorage.getItem(STORAGE_KEY);
|
||||||
|
if (storageLevel) {
|
||||||
|
return normalizeLevel(storageLevel);
|
||||||
|
}
|
||||||
|
} catch (_error) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return DEFAULT_LEVEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
function shouldLog(level) {
|
||||||
|
return LOG_LEVELS[level] >= LOG_LEVELS[getConfiguredLevel()];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getConsoleMethod(level) {
|
||||||
|
switch (level) {
|
||||||
|
case 'debug':
|
||||||
|
return console.debug;
|
||||||
|
case 'info':
|
||||||
|
return console.info;
|
||||||
|
case 'warn':
|
||||||
|
return console.warn;
|
||||||
|
case 'error':
|
||||||
|
return console.error;
|
||||||
|
default:
|
||||||
|
return console.log;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function emit(level, scope, args) {
|
||||||
|
if (!shouldLog(level)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const prefix = scope ? `[${scope}]` : '[app]';
|
||||||
|
getConsoleMethod(level)(prefix, ...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createLogger(scope) {
|
||||||
|
return {
|
||||||
|
debug: (...args) => emit('debug', scope, args),
|
||||||
|
info: (...args) => emit('info', scope, args),
|
||||||
|
warn: (...args) => emit('warn', scope, args),
|
||||||
|
error: (...args) => emit('error', scope, args)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setBrowserLogLevel(level) {
|
||||||
|
const normalized = normalizeLevel(level);
|
||||||
|
localStorage.setItem(STORAGE_KEY, normalized);
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
@@ -9,6 +9,9 @@ import {
|
|||||||
loadUserSettings
|
loadUserSettings
|
||||||
} from './connectview.js';
|
} from './connectview.js';
|
||||||
import { createInviteController } from './invite-controller.js';
|
import { createInviteController } from './invite-controller.js';
|
||||||
|
import { createLogger } from './logger.js';
|
||||||
|
|
||||||
|
const logger = createLogger('main');
|
||||||
|
|
||||||
let connectionId = '';
|
let connectionId = '';
|
||||||
let currentView = 'connect';
|
let currentView = 'connect';
|
||||||
@@ -43,10 +46,10 @@ async function switchToCallView(targetConnectionId) {
|
|||||||
renderer.renderHeaderTitle();
|
renderer.renderHeaderTitle();
|
||||||
callViewController.bindDomEvents();
|
callViewController.bindDomEvents();
|
||||||
|
|
||||||
console.log('Video call app initialized successfully');
|
logger.debug('Video call app initialized successfully');
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error initializing app:', error);
|
logger.error('Error initializing app:', error);
|
||||||
showNotification('初始化失败,请刷新页面重试', 'error');
|
showNotification('初始化失败,请刷新页面重试', 'error');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -116,9 +119,9 @@ window.addEventListener('DOMContentLoaded', async () => {
|
|||||||
inviteController.showCallRequestDialog(invitePayload);
|
inviteController.showCallRequestDialog(invitePayload);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('SPA initialized, showing connect view');
|
logger.debug('SPA initialized, showing connect view');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error initializing SPA:', error);
|
logger.error('Error initializing SPA:', error);
|
||||||
showNotification('初始化失败,请刷新页面重试', 'error');
|
showNotification('初始化失败,请刷新页面重试', 'error');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
import { createLogger } from './logger.js';
|
||||||
|
|
||||||
|
const logger = createLogger('profile');
|
||||||
const DEFAULT_AVATAR = '/images/p1.png';
|
const DEFAULT_AVATAR = '/images/p1.png';
|
||||||
const MAX_AVATAR_SIZE = 2 * 1024 * 1024;
|
const MAX_AVATAR_SIZE = 2 * 1024 * 1024;
|
||||||
const USER_ID_PREFIX = 'user_';
|
const USER_ID_PREFIX = 'user_';
|
||||||
@@ -100,7 +103,7 @@ export function createProfileSettingsController({ store, notify }) {
|
|||||||
updateUserName(settings.name || '\u6211');
|
updateUserName(settings.name || '\u6211');
|
||||||
setAvatarPreview(settings.avatar || DEFAULT_AVATAR);
|
setAvatarPreview(settings.avatar || DEFAULT_AVATAR);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading user settings:', error);
|
logger.error('Error loading user settings:', error);
|
||||||
setAvatarPreview(DEFAULT_AVATAR);
|
setAvatarPreview(DEFAULT_AVATAR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152,7 +155,7 @@ export function createProfileSettingsController({ store, notify }) {
|
|||||||
saveSettings();
|
saveSettings();
|
||||||
notify('\u5934\u50cf\u4e0a\u4f20\u6210\u529f', 'success');
|
notify('\u5934\u50cf\u4e0a\u4f20\u6210\u529f', 'success');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error uploading avatar:', error);
|
logger.error('Error uploading avatar:', error);
|
||||||
setAvatarPreview(DEFAULT_AVATAR);
|
setAvatarPreview(DEFAULT_AVATAR);
|
||||||
notify('\u5934\u50cf\u4e0a\u4f20\u5931\u8d25\uff0c\u8bf7\u91cd\u8bd5', 'error');
|
notify('\u5934\u50cf\u4e0a\u4f20\u5931\u8d25\uff0c\u8bf7\u91cd\u8bd5', 'error');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
import { createParticipantTile, getParticipantTile } from './renderer-participant-grid.js';
|
import { createParticipantTile, getParticipantTile } from './renderer-participant-grid.js';
|
||||||
|
import { createLogger } from './logger.js';
|
||||||
|
|
||||||
|
const logger = createLogger('renderer-media');
|
||||||
|
|
||||||
export function getVideoResolution(track) {
|
export function getVideoResolution(track) {
|
||||||
if (track && track.getSettings) {
|
if (track && track.getSettings) {
|
||||||
@@ -47,18 +50,18 @@ export function renderParticipantStreamMedia({
|
|||||||
if (!tile) {
|
if (!tile) {
|
||||||
tile = createParticipantTile(connectionId, displayName);
|
tile = createParticipantTile(connectionId, displayName);
|
||||||
grid.appendChild(tile);
|
grid.appendChild(tile);
|
||||||
console.log(`Created participant video tile for ${connectionId}`);
|
logger.debug(`Created participant video tile for ${connectionId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const video = tile.querySelector('video');
|
const video = tile.querySelector('video');
|
||||||
if (video && stream) {
|
if (video && stream) {
|
||||||
if (video.srcObject === stream) {
|
if (video.srcObject === stream) {
|
||||||
console.log(`Same stream for participant ${connectionId}, ensuring playback`);
|
logger.debug(`Same stream for participant ${connectionId}, ensuring playback`);
|
||||||
video.play().catch(error => console.log('Auto-play prevented:', error.message));
|
video.play().catch(error => logger.debug('Auto-play prevented:', error.message));
|
||||||
} else {
|
} else {
|
||||||
video.srcObject = stream;
|
video.srcObject = stream;
|
||||||
video.play().catch(error => console.log('Auto-play prevented:', error.message));
|
video.play().catch(error => logger.debug('Auto-play prevented:', error.message));
|
||||||
console.log(`Set remote stream for participant tile ${connectionId}`);
|
logger.debug(`Set remote stream for participant tile ${connectionId}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,15 +89,15 @@ export function renderSingleRemoteStreamMedia({
|
|||||||
connectingOverlay
|
connectingOverlay
|
||||||
}) {
|
}) {
|
||||||
if (!remoteVideo || !stream) {
|
if (!remoteVideo || !stream) {
|
||||||
console.error('Either remoteVideo element or stream is missing');
|
logger.error('Either remoteVideo element or stream is missing');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Rendering remote stream:', stream, 'tracks:', stream.getTracks().map(track => `${track.kind}(${track.readyState})`));
|
logger.debug('Rendering remote stream:', stream, 'tracks:', stream.getTracks().map(track => `${track.kind}(${track.readyState})`));
|
||||||
|
|
||||||
if (remoteVideo.srcObject === stream) {
|
if (remoteVideo.srcObject === stream) {
|
||||||
console.log('Same stream object, track added - ensuring playback');
|
logger.debug('Same stream object, track added - ensuring playback');
|
||||||
remoteVideo.play().catch(error => console.log('Auto-play prevented:', error.message));
|
remoteVideo.play().catch(error => logger.debug('Auto-play prevented:', error.message));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,7 +106,7 @@ export function renderSingleRemoteStreamMedia({
|
|||||||
remoteVideo.playsinline = true;
|
remoteVideo.playsinline = true;
|
||||||
remoteVideo.muted = false;
|
remoteVideo.muted = false;
|
||||||
remoteVideo.play().catch(error => {
|
remoteVideo.play().catch(error => {
|
||||||
console.log('Auto-play prevented, will retry on interaction:', error.message);
|
logger.debug('Auto-play prevented, will retry on interaction:', error.message);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (disconnectedOverlay) {
|
if (disconnectedOverlay) {
|
||||||
@@ -112,10 +115,10 @@ export function renderSingleRemoteStreamMedia({
|
|||||||
|
|
||||||
const videoTracks = stream.getVideoTracks();
|
const videoTracks = stream.getVideoTracks();
|
||||||
const audioTracks = stream.getAudioTracks();
|
const audioTracks = stream.getAudioTracks();
|
||||||
console.log(`Stream has ${videoTracks.length} video tracks, ${audioTracks.length} audio tracks`);
|
logger.debug(`Stream has ${videoTracks.length} video tracks, ${audioTracks.length} audio tracks`);
|
||||||
|
|
||||||
if (videoTracks.length === 0) {
|
if (videoTracks.length === 0) {
|
||||||
console.log('Audio-only stream, waiting for video track...');
|
logger.debug('Audio-only stream, waiting for video track...');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +168,7 @@ export function removeParticipantTile({
|
|||||||
video.srcObject = null;
|
video.srcObject = null;
|
||||||
}
|
}
|
||||||
tile.remove();
|
tile.remove();
|
||||||
console.log(`Removed participant video tile for ${connectionId}`);
|
logger.debug(`Removed participant video tile for ${connectionId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const remainingTiles = grid.querySelectorAll('[data-participant-id]');
|
const remainingTiles = grid.querySelectorAll('[data-participant-id]');
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ import {
|
|||||||
renderParticipantStreamMedia,
|
renderParticipantStreamMedia,
|
||||||
renderSingleRemoteStreamMedia
|
renderSingleRemoteStreamMedia
|
||||||
} from './renderer-media.js';
|
} from './renderer-media.js';
|
||||||
|
import { createLogger } from './logger.js';
|
||||||
|
|
||||||
|
const logger = createLogger('renderer');
|
||||||
|
|
||||||
const GRID_LAYOUT = {
|
const GRID_LAYOUT = {
|
||||||
maxColumns: 3,
|
maxColumns: 3,
|
||||||
@@ -317,13 +320,13 @@ class UIRenderer {
|
|||||||
this.elements.localVideo.srcObject = stream;
|
this.elements.localVideo.srcObject = stream;
|
||||||
this.elements.localVideo.autoplay = true;
|
this.elements.localVideo.autoplay = true;
|
||||||
this.elements.localVideo.muted = true;
|
this.elements.localVideo.muted = true;
|
||||||
console.log('srcObject set successfully:', this.elements.localVideo.srcObject);
|
logger.debug('srcObject set successfully:', this.elements.localVideo.srcObject);
|
||||||
|
|
||||||
if (this.elements.disconnectedOverlay) {
|
if (this.elements.disconnectedOverlay) {
|
||||||
this.elements.disconnectedOverlay.classList.add('hidden');
|
this.elements.disconnectedOverlay.classList.add('hidden');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.error('Either localVideo element or stream is missing');
|
logger.error('Either localVideo element or stream is missing');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,7 +355,7 @@ class UIRenderer {
|
|||||||
const grid = this.elements.participantGrid;
|
const grid = this.elements.participantGrid;
|
||||||
if (!grid) return;
|
if (!grid) return;
|
||||||
updateParticipantTilePlaceholder(grid, participantId, showPlaceholder);
|
updateParticipantTilePlaceholder(grid, participantId, showPlaceholder);
|
||||||
console.log(`Updated placeholder for participant ${participantId}: ${showPlaceholder ? 'shown' : 'hidden'}`);
|
logger.debug(`Updated placeholder for participant ${participantId}: ${showPlaceholder ? 'shown' : 'hidden'}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
syncParticipantTileNames(participants) {
|
syncParticipantTileNames(participants) {
|
||||||
@@ -369,7 +372,7 @@ class UIRenderer {
|
|||||||
if (!grid) return;
|
if (!grid) return;
|
||||||
syncParticipantTileName(grid, participantId, name);
|
syncParticipantTileName(grid, participantId, name);
|
||||||
if (name) {
|
if (name) {
|
||||||
console.log(`Updated tile name for participant ${participantId}: ${name}`);
|
logger.debug(`Updated tile name for participant ${participantId}: ${name}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,13 +511,13 @@ class UIRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderCallEnded() {
|
renderCallEnded() {
|
||||||
console.log('Call ended');
|
logger.debug('Call ended');
|
||||||
clearParticipantGrid(this.elements.participantGrid);
|
clearParticipantGrid(this.elements.participantGrid);
|
||||||
window.location.href = './endcall/endcall.html';
|
window.location.href = './endcall/endcall.html';
|
||||||
}
|
}
|
||||||
|
|
||||||
renderParticipantLeft(connectionId) {
|
renderParticipantLeft(connectionId) {
|
||||||
console.log(`Participant left: ${connectionId}, updating UI`);
|
logger.debug(`Participant left: ${connectionId}, updating UI`);
|
||||||
removeParticipantTile({
|
removeParticipantTile({
|
||||||
grid: this.elements.participantGrid,
|
grid: this.elements.participantGrid,
|
||||||
connectionId,
|
connectionId,
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
import { Signaling, WebSocketSignaling } from "../../module/signaling.js";
|
import { Signaling, WebSocketSignaling } from "../../module/signaling.js";
|
||||||
|
import { createLogger } from './logger.js';
|
||||||
|
|
||||||
|
const logger = createLogger('signaling');
|
||||||
|
|
||||||
const INVITE_EVENT_NAMES = Object.freeze([
|
const INVITE_EVENT_NAMES = Object.freeze([
|
||||||
'invite-call',
|
'invite-call',
|
||||||
@@ -72,7 +75,7 @@ function readStoredSocketUserInfo() {
|
|||||||
try {
|
try {
|
||||||
return JSON.parse(localStorage.getItem('userSettings') || '{}');
|
return JSON.parse(localStorage.getItem('userSettings') || '{}');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error parsing user settings:', error);
|
logger.error('Error parsing user settings:', error);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ import { AUDIO_CONFIG, VAD_CONFIG, VIDEO_ONLY_CONSTRAINT, buildVideoConstraints,
|
|||||||
import { buildStatsLogPayload, createAudioAnalyser, getAudioLevel } from './media-monitoring.js';
|
import { buildStatsLogPayload, createAudioAnalyser, getAudioLevel } from './media-monitoring.js';
|
||||||
import { bindInviteSocketEvents, buildSocketUserInfoPayload, createSignalingInstance, ensureSignalingStarted, getActiveSignalingInstance, sendInviteSignal, sendSocketUserInfo } from './signaling-session.js';
|
import { bindInviteSocketEvents, buildSocketUserInfoPayload, createSignalingInstance, ensureSignalingStarted, getActiveSignalingInstance, sendInviteSignal, sendSocketUserInfo } from './signaling-session.js';
|
||||||
import { getNetworkQualityFromSummary, summarizeInboundStats } from './webrtc-stats.js';
|
import { getNetworkQualityFromSummary, summarizeInboundStats } from './webrtc-stats.js';
|
||||||
|
import { createLogger } from './logger.js';
|
||||||
|
|
||||||
|
const logger = createLogger('store');
|
||||||
class CallStateManager {
|
class CallStateManager {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.state = {
|
this.state = {
|
||||||
@@ -55,11 +58,11 @@ class CallStateManager {
|
|||||||
}
|
}
|
||||||
if (settings.resolution) {
|
if (settings.resolution) {
|
||||||
this._savedResolution = settings.resolution;
|
this._savedResolution = settings.resolution;
|
||||||
console.log(`已恢复分辨率设置: ${settings.resolution.width}x${settings.resolution.height}`);
|
logger.debug(`已恢复分辨率设置: ${settings.resolution.width}x${settings.resolution.height}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error('Error loading user settings:', error);
|
logger.error('Error loading user settings:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,9 +72,9 @@ class CallStateManager {
|
|||||||
}
|
}
|
||||||
async getLocalStream() {
|
async getLocalStream() {
|
||||||
try {
|
try {
|
||||||
console.log('Requesting camera permission...');
|
logger.debug('Requesting camera permission...');
|
||||||
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
|
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
|
||||||
console.error('getUserMedia is not supported');
|
logger.error('getUserMedia is not supported');
|
||||||
throw new Error('getUserMedia is not supported');
|
throw new Error('getUserMedia is not supported');
|
||||||
}
|
}
|
||||||
const videoConstraints = buildVideoConstraints(this._savedResolution);
|
const videoConstraints = buildVideoConstraints(this._savedResolution);
|
||||||
@@ -79,13 +82,13 @@ class CallStateManager {
|
|||||||
video: videoConstraints,
|
video: videoConstraints,
|
||||||
audio: AUDIO_CONFIG
|
audio: AUDIO_CONFIG
|
||||||
});
|
});
|
||||||
console.log('Stream obtained successfully:', stream);
|
logger.debug('Stream obtained successfully:', stream);
|
||||||
console.log('Video tracks:', stream.getVideoTracks());
|
logger.debug('Video tracks:', stream.getVideoTracks());
|
||||||
console.log('Audio tracks:', stream.getAudioTracks());
|
logger.debug('Audio tracks:', stream.getAudioTracks());
|
||||||
this.state.localStream = stream;
|
this.state.localStream = stream;
|
||||||
this.state.session.localUser.mediaState.video = true;
|
this.state.session.localUser.mediaState.video = true;
|
||||||
this.state.session.localUser.mediaState.audio = true;
|
this.state.session.localUser.mediaState.audio = true;
|
||||||
console.log('Local stream stored, notifying UI...');
|
logger.debug('Local stream stored, notifying UI...');
|
||||||
this.notify({ type: 'LOCAL_STREAM_OBTAINED', stream });
|
this.notify({ type: 'LOCAL_STREAM_OBTAINED', stream });
|
||||||
this.notify({ type: 'LOCAL_MEDIA_CHANGE', mediaType: 'video', value: true });
|
this.notify({ type: 'LOCAL_MEDIA_CHANGE', mediaType: 'video', value: true });
|
||||||
this.notify({ type: 'LOCAL_MEDIA_CHANGE', mediaType: 'audio', value: true });
|
this.notify({ type: 'LOCAL_MEDIA_CHANGE', mediaType: 'audio', value: true });
|
||||||
@@ -93,7 +96,7 @@ class CallStateManager {
|
|||||||
this.startActivityDetection(this.state.localStream, { isLocal: true });
|
this.startActivityDetection(this.state.localStream, { isLocal: true });
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error('Error getting local stream:', error);
|
logger.error('Error getting local stream:', error);
|
||||||
this.state.session.localUser.mediaState.video = false;
|
this.state.session.localUser.mediaState.video = false;
|
||||||
this.state.session.localUser.mediaState.audio = false;
|
this.state.session.localUser.mediaState.audio = false;
|
||||||
this.notify({ type: 'LOCAL_MEDIA_CHANGE', mediaType: 'video', value: false });
|
this.notify({ type: 'LOCAL_MEDIA_CHANGE', mediaType: 'video', value: false });
|
||||||
@@ -133,7 +136,7 @@ class CallStateManager {
|
|||||||
this.startActivityDetection(this.state.localStream, { isLocal: true });
|
this.startActivityDetection(this.state.localStream, { isLocal: true });
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error('Error reopening video:', error);
|
logger.error('Error reopening video:', error);
|
||||||
this.state.session.localUser.mediaState.video = false;
|
this.state.session.localUser.mediaState.video = false;
|
||||||
this._notifyLocalMediaChange('video', false);
|
this._notifyLocalMediaChange('video', false);
|
||||||
}
|
}
|
||||||
@@ -162,7 +165,7 @@ class CallStateManager {
|
|||||||
if (!this.renderstreaming) {
|
if (!this.renderstreaming) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log('Updating video track in WebRTC connection');
|
logger.debug('Updating video track in WebRTC connection');
|
||||||
if (this.role === 'host') {
|
if (this.role === 'host') {
|
||||||
const participantIds = Object.keys(this.state.remoteStreams);
|
const participantIds = Object.keys(this.state.remoteStreams);
|
||||||
for (const participantId of participantIds) {
|
for (const participantId of participantIds) {
|
||||||
@@ -190,12 +193,12 @@ class CallStateManager {
|
|||||||
for (const transceiver of videoTransceivers) {
|
for (const transceiver of videoTransceivers) {
|
||||||
try {
|
try {
|
||||||
await transceiver.sender.replaceTrack(newVideoTrack);
|
await transceiver.sender.replaceTrack(newVideoTrack);
|
||||||
console.log(participantId
|
logger.debug(participantId
|
||||||
? `Replaced video track for participant ${participantId}`
|
? `Replaced video track for participant ${participantId}`
|
||||||
: 'Successfully replaced video track');
|
: 'Successfully replaced video track');
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error(participantId
|
logger.error(participantId
|
||||||
? `Error replacing video track for ${participantId}:`
|
? `Error replacing video track for ${participantId}:`
|
||||||
: 'Error replacing video track:', error);
|
: 'Error replacing video track:', error);
|
||||||
}
|
}
|
||||||
@@ -205,14 +208,14 @@ class CallStateManager {
|
|||||||
try {
|
try {
|
||||||
if (participantId) {
|
if (participantId) {
|
||||||
this.renderstreaming.addTransceiver(newVideoTrack, { direction: 'sendonly' }, participantId);
|
this.renderstreaming.addTransceiver(newVideoTrack, { direction: 'sendonly' }, participantId);
|
||||||
console.log(`Added new video transceiver for participant ${participantId}`);
|
logger.debug(`Added new video transceiver for participant ${participantId}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.renderstreaming.addTransceiver(newVideoTrack, { direction: 'sendonly' });
|
this.renderstreaming.addTransceiver(newVideoTrack, { direction: 'sendonly' });
|
||||||
console.log('Added new video transceiver');
|
logger.debug('Added new video transceiver');
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error(participantId
|
logger.error(participantId
|
||||||
? `Error adding video transceiver for ${participantId}:`
|
? `Error adding video transceiver for ${participantId}:`
|
||||||
: 'Error adding video transceiver:', error);
|
: 'Error adding video transceiver:', error);
|
||||||
}
|
}
|
||||||
@@ -262,10 +265,10 @@ class CallStateManager {
|
|||||||
this._signaling = signaling;
|
this._signaling = signaling;
|
||||||
this._inviteEventSignaling = bindInviteSocketEvents(this._signaling, this.socketEventHandlers, this._inviteEventSignaling);
|
this._inviteEventSignaling = bindInviteSocketEvents(this._signaling, this.socketEventHandlers, this._inviteEventSignaling);
|
||||||
if (reused) {
|
if (reused) {
|
||||||
console.log('Signaling already connected, reusing existing instance');
|
logger.debug('Signaling already connected, reusing existing instance');
|
||||||
return this._signaling;
|
return this._signaling;
|
||||||
}
|
}
|
||||||
console.log('Signaling connected (WebSocket only, no room yet)');
|
logger.debug('Signaling connected (WebSocket only, no room yet)');
|
||||||
return this._signaling;
|
return this._signaling;
|
||||||
}
|
}
|
||||||
getActiveSignaling() {
|
getActiveSignaling() {
|
||||||
@@ -295,7 +298,7 @@ class CallStateManager {
|
|||||||
this.state.session.status = 'connecting';
|
this.state.session.status = 'connecting';
|
||||||
this.notify({ type: 'CALL_STATUS_CHANGE', status: 'connecting' });
|
this.notify({ type: 'CALL_STATUS_CHANGE', status: 'connecting' });
|
||||||
if (!this.state.localStream) {
|
if (!this.state.localStream) {
|
||||||
console.log('Local stream not available, waiting for initialization...');
|
logger.debug('Local stream not available, waiting for initialization...');
|
||||||
await new Promise((resolve) => {
|
await new Promise((resolve) => {
|
||||||
const checkStream = () => {
|
const checkStream = () => {
|
||||||
if (this.state.localStream) {
|
if (this.state.localStream) {
|
||||||
@@ -320,7 +323,7 @@ class CallStateManager {
|
|||||||
}
|
}
|
||||||
_registerCallbacks() {
|
_registerCallbacks() {
|
||||||
this.renderstreaming.onNewPeer = (participantId) => {
|
this.renderstreaming.onNewPeer = (participantId) => {
|
||||||
console.log(`New peer created for ${participantId}, adding local tracks`);
|
logger.debug(`New peer created for ${participantId}, adding local tracks`);
|
||||||
if (this.state.localStream) {
|
if (this.state.localStream) {
|
||||||
const tracks = this.state.localStream.getTracks();
|
const tracks = this.state.localStream.getTracks();
|
||||||
for (const track of tracks) {
|
for (const track of tracks) {
|
||||||
@@ -337,7 +340,7 @@ class CallStateManager {
|
|||||||
if (data.participantId) {
|
if (data.participantId) {
|
||||||
this.selfParticipantId = data.participantId;
|
this.selfParticipantId = data.participantId;
|
||||||
}
|
}
|
||||||
console.log(`Connected as ${this.role}, participantId: ${this.selfParticipantId}`);
|
logger.debug(`Connected as ${this.role}, participantId: ${this.selfParticipantId}`);
|
||||||
}
|
}
|
||||||
this.state.session.status = 'ongoing';
|
this.state.session.status = 'ongoing';
|
||||||
this.notify({ type: 'CALL_STATUS_CHANGE', status: 'ongoing' });
|
this.notify({ type: 'CALL_STATUS_CHANGE', status: 'ongoing' });
|
||||||
@@ -349,7 +352,7 @@ class CallStateManager {
|
|||||||
}
|
}
|
||||||
this.state.session.localUser.mediaState.audio = false;
|
this.state.session.localUser.mediaState.audio = false;
|
||||||
this.notify({ type: 'LOCAL_MEDIA_CHANGE', mediaType: 'audio', value: false });
|
this.notify({ type: 'LOCAL_MEDIA_CHANGE', mediaType: 'audio', value: false });
|
||||||
console.log('Participant joined with audio muted by default');
|
logger.debug('Participant joined with audio muted by default');
|
||||||
}
|
}
|
||||||
this.sendMessage('user-info', {
|
this.sendMessage('user-info', {
|
||||||
id: this.state.session.localUser.id,
|
id: this.state.session.localUser.id,
|
||||||
@@ -361,16 +364,16 @@ class CallStateManager {
|
|||||||
this.showStatsMessage();
|
this.showStatsMessage();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.error('Local stream is not available');
|
logger.error('Local stream is not available');
|
||||||
showNotification('本地视频流不可用', 'error');
|
showNotification('本地视频流不可用', 'error');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.renderstreaming.onDisconnect = () => {
|
this.renderstreaming.onDisconnect = () => {
|
||||||
console.log('Received disconnect from server, host left or room closed');
|
logger.debug('Received disconnect from server, host left or room closed');
|
||||||
this.hangUp();
|
this.hangUp();
|
||||||
};
|
};
|
||||||
this.renderstreaming.onGotAnswer = (connectionId) => {
|
this.renderstreaming.onGotAnswer = (connectionId) => {
|
||||||
console.log('SDP Answer received, resetting encoding parameters for connectionId:', connectionId);
|
logger.debug('SDP Answer received, resetting encoding parameters for connectionId:', connectionId);
|
||||||
if (this.role === 'host') {
|
if (this.role === 'host') {
|
||||||
const allParticipantIds = Object.keys(this.state.remoteStreams || {});
|
const allParticipantIds = Object.keys(this.state.remoteStreams || {});
|
||||||
for (const pid of allParticipantIds) {
|
for (const pid of allParticipantIds) {
|
||||||
@@ -382,13 +385,13 @@ class CallStateManager {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.renderstreaming.onParticipantJoined = (participantId) => {
|
this.renderstreaming.onParticipantJoined = (participantId) => {
|
||||||
console.log(`Participant joined: ${participantId}`);
|
logger.debug(`Participant joined: ${participantId}`);
|
||||||
this._upsertParticipant(participantId);
|
this._upsertParticipant(participantId);
|
||||||
this._notifyParticipantsUpdate();
|
this._notifyParticipantsUpdate();
|
||||||
this.broadcastParticipantsList();
|
this.broadcastParticipantsList();
|
||||||
};
|
};
|
||||||
this.renderstreaming.onParticipantLeft = (participantId) => {
|
this.renderstreaming.onParticipantLeft = (participantId) => {
|
||||||
console.log(`Participant left: ${participantId}, room still active`);
|
logger.debug(`Participant left: ${participantId}, room still active`);
|
||||||
this.updateRemoteUserStatus('offline');
|
this.updateRemoteUserStatus('offline');
|
||||||
this.updateRemoteUserNetworkQuality('no_signal');
|
this.updateRemoteUserNetworkQuality('no_signal');
|
||||||
showNotification('对方已离开通话', 'warning');
|
showNotification('对方已离开通话', 'warning');
|
||||||
@@ -428,14 +431,14 @@ class CallStateManager {
|
|||||||
}
|
}
|
||||||
this.durationSynced = false;
|
this.durationSynced = false;
|
||||||
const isHost = this.role === 'host';
|
const isHost = this.role === 'host';
|
||||||
console.log(`Disconnect peer on ${this.connectionId}. Role: ${this.role}`);
|
logger.debug(`Disconnect peer on ${this.connectionId}. Role: ${this.role}`);
|
||||||
if (this.renderstreaming) {
|
if (this.renderstreaming) {
|
||||||
try {
|
try {
|
||||||
await this.renderstreaming.deleteConnection();
|
await this.renderstreaming.deleteConnection();
|
||||||
await this.renderstreaming.stop();
|
await this.renderstreaming.stop();
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error('Error during hangUp:', error);
|
logger.error('Error during hangUp:', error);
|
||||||
}
|
}
|
||||||
this.renderstreaming = null;
|
this.renderstreaming = null;
|
||||||
}
|
}
|
||||||
@@ -463,7 +466,7 @@ class CallStateManager {
|
|||||||
const isHost = this.role === 'host';
|
const isHost = this.role === 'host';
|
||||||
const targetStream = this._getOrCreateRemoteStream(trackParticipantId, isHost);
|
const targetStream = this._getOrCreateRemoteStream(trackParticipantId, isHost);
|
||||||
this._replaceTrackOfSameKind(targetStream, data.track);
|
this._replaceTrackOfSameKind(targetStream, data.track);
|
||||||
console.log('Added new track:', data.track.kind, 'for participant:', trackParticipantId);
|
logger.debug('Added new track:', data.track.kind, 'for participant:', trackParticipantId);
|
||||||
if (isHost && !this.state.participants[trackParticipantId]) {
|
if (isHost && !this.state.participants[trackParticipantId]) {
|
||||||
this._upsertParticipant(trackParticipantId);
|
this._upsertParticipant(trackParticipantId);
|
||||||
this._notifyParticipantsUpdate();
|
this._notifyParticipantsUpdate();
|
||||||
@@ -500,7 +503,7 @@ class CallStateManager {
|
|||||||
const existingTracks = targetStream.getTracks().filter(existingTrack => existingTrack.kind === track.kind);
|
const existingTracks = targetStream.getTracks().filter(existingTrack => existingTrack.kind === track.kind);
|
||||||
existingTracks.forEach(existingTrack => {
|
existingTracks.forEach(existingTrack => {
|
||||||
targetStream.removeTrack(existingTrack);
|
targetStream.removeTrack(existingTrack);
|
||||||
console.log('Removed old track:', existingTrack.kind);
|
logger.debug('Removed old track:', existingTrack.kind);
|
||||||
});
|
});
|
||||||
targetStream.addTrack(track);
|
targetStream.addTrack(track);
|
||||||
}
|
}
|
||||||
@@ -512,13 +515,13 @@ class CallStateManager {
|
|||||||
connectionId: trackParticipantId,
|
connectionId: trackParticipantId,
|
||||||
isHost
|
isHost
|
||||||
});
|
});
|
||||||
console.log('Notified UI about remote stream update');
|
logger.debug('Notified UI about remote stream update');
|
||||||
};
|
};
|
||||||
if (trackKind === 'audio' && targetStream.getVideoTracks().length === 0) {
|
if (trackKind === 'audio' && targetStream.getVideoTracks().length === 0) {
|
||||||
console.log('Audio track arrived first, delaying stream notification for video track...');
|
logger.debug('Audio track arrived first, delaying stream notification for video track...');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const nowHasVideo = targetStream.getVideoTracks().length > 0;
|
const nowHasVideo = targetStream.getVideoTracks().length > 0;
|
||||||
console.log(`After delay, stream has video: ${nowHasVideo}`);
|
logger.debug(`After delay, stream has video: ${nowHasVideo}`);
|
||||||
notifyStreamUpdate();
|
notifyStreamUpdate();
|
||||||
}, 200);
|
}, 200);
|
||||||
return;
|
return;
|
||||||
@@ -526,7 +529,7 @@ class CallStateManager {
|
|||||||
notifyStreamUpdate();
|
notifyStreamUpdate();
|
||||||
}
|
}
|
||||||
_handleRenderStreamingMessage(data) {
|
_handleRenderStreamingMessage(data) {
|
||||||
console.log('收到信令消息:', data);
|
logger.debug('收到信令消息:', data);
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case 'chat-message':
|
case 'chat-message':
|
||||||
this._handleChatMessage(data);
|
this._handleChatMessage(data);
|
||||||
@@ -578,7 +581,7 @@ class CallStateManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_handleMediaStateChangedMessage(data) {
|
_handleMediaStateChangedMessage(data) {
|
||||||
console.log('收到媒体状态更新:', data.data, 'from participant:', data.participantId);
|
logger.debug('收到媒体状态更新:', data.data, 'from participant:', data.participantId);
|
||||||
if (this.role === 'host') {
|
if (this.role === 'host') {
|
||||||
if (data.participantId && this.state.participants[data.participantId]) {
|
if (data.participantId && this.state.participants[data.participantId]) {
|
||||||
this._upsertParticipant(data.participantId, {
|
this._upsertParticipant(data.participantId, {
|
||||||
@@ -600,12 +603,12 @@ class CallStateManager {
|
|||||||
if (data.participantId === this.selfParticipantId) {
|
if (data.participantId === this.selfParticipantId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log('Received media-state-changed from Host, updating remoteUser:', data.data);
|
logger.debug('Received media-state-changed from Host, updating remoteUser:', data.data);
|
||||||
this.updateRemoteMedia(data.data, data.participantId);
|
this.updateRemoteMedia(data.data, data.participantId);
|
||||||
this._notifyParticipantsUpdate();
|
this._notifyParticipantsUpdate();
|
||||||
}
|
}
|
||||||
_handleUserInfoMessage(data) {
|
_handleUserInfoMessage(data) {
|
||||||
console.log('收到用户信息:', data.data, 'from participant:', data.participantId);
|
logger.debug('收到用户信息:', data.data, 'from participant:', data.participantId);
|
||||||
if (!data.data) {
|
if (!data.data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -629,7 +632,7 @@ class CallStateManager {
|
|||||||
if (this.role === 'host' || !data.data) {
|
if (this.role === 'host' || !data.data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log('收到成员同步列表:', data.data);
|
logger.debug('收到成员同步列表:', data.data);
|
||||||
this.state.participants = omitParticipant(data.data, this.selfParticipantId);
|
this.state.participants = omitParticipant(data.data, this.selfParticipantId);
|
||||||
this._notifyParticipantsUpdate();
|
this._notifyParticipantsUpdate();
|
||||||
this._syncCallDuration(data.callDuration);
|
this._syncCallDuration(data.callDuration);
|
||||||
@@ -646,7 +649,7 @@ class CallStateManager {
|
|||||||
this.durationSynced = true;
|
this.durationSynced = true;
|
||||||
this._startDurationTimer();
|
this._startDurationTimer();
|
||||||
this.notify({ type: 'DURATION_UPDATE', duration: this.state.session.duration });
|
this.notify({ type: 'DURATION_UPDATE', duration: this.state.session.duration });
|
||||||
console.log(`Call duration synced: ${callDuration} seconds`);
|
logger.debug(`Call duration synced: ${callDuration} seconds`);
|
||||||
}
|
}
|
||||||
_startDurationTimer() {
|
_startDurationTimer() {
|
||||||
if (this.durationInterval) {
|
if (this.durationInterval) {
|
||||||
@@ -706,7 +709,7 @@ class CallStateManager {
|
|||||||
data: memberList,
|
data: memberList,
|
||||||
callDuration: this.state.session.duration
|
callDuration: this.state.session.duration
|
||||||
});
|
});
|
||||||
console.log('Broadcast participants list:', Object.keys(memberList));
|
logger.debug('Broadcast participants list:', Object.keys(memberList));
|
||||||
}
|
}
|
||||||
setCodecPreferences(participantId) {
|
setCodecPreferences(participantId) {
|
||||||
const capabilities = RTCRtpSender.getCapabilities('video');
|
const capabilities = RTCRtpSender.getCapabilities('video');
|
||||||
@@ -744,10 +747,10 @@ class CallStateManager {
|
|||||||
t.setCodecPreferences(selectedCodecs);
|
t.setCodecPreferences(selectedCodecs);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
console.error('Error setting codec preferences:', e);
|
logger.error('Error setting codec preferences:', e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
console.log(`Codec preferences set: ${selectedCodecs.map(c => c.mimeType).join(' > ')}`);
|
logger.debug(`Codec preferences set: ${selectedCodecs.map(c => c.mimeType).join(' > ')}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -777,10 +780,10 @@ class CallStateManager {
|
|||||||
params.degradationPreference = 'maintain-resolution';
|
params.degradationPreference = 'maintain-resolution';
|
||||||
}
|
}
|
||||||
sender.setParameters(params);
|
sender.setParameters(params);
|
||||||
console.log(`Set video encoding: maxBitrate=${maxBitrate / 1000000}Mbps, scaleResolutionDownBy=1.0, xGoogleMinBitrate=${Math.floor(maxBitrate * 0.5)}${participantId ? ` for ${participantId}` : ''}`);
|
logger.debug(`Set video encoding: maxBitrate=${maxBitrate / 1000000}Mbps, scaleResolutionDownBy=1.0, xGoogleMinBitrate=${Math.floor(maxBitrate * 0.5)}${participantId ? ` for ${participantId}` : ''}`);
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error('Error setting video encoding parameters:', error);
|
logger.error('Error setting video encoding parameters:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -802,7 +805,7 @@ class CallStateManager {
|
|||||||
height: { ideal: height, max: height },
|
height: { ideal: height, max: height },
|
||||||
frameRate: { ideal: 30, max: 30 }
|
frameRate: { ideal: 30, max: 30 }
|
||||||
});
|
});
|
||||||
console.log(`分辨率已切换为 ${width}x${height}`);
|
logger.debug(`分辨率已切换为 ${width}x${height}`);
|
||||||
const maxBitrate = getTargetResolutionBitrate(height);
|
const maxBitrate = getTargetResolutionBitrate(height);
|
||||||
this._applyMaxBitrate(maxBitrate);
|
this._applyMaxBitrate(maxBitrate);
|
||||||
const userSettings = JSON.parse(localStorage.getItem('userSettings') || '{}');
|
const userSettings = JSON.parse(localStorage.getItem('userSettings') || '{}');
|
||||||
@@ -812,7 +815,7 @@ class CallStateManager {
|
|||||||
showNotification('已切换为 ' + label, 'success');
|
showNotification('已切换为 ' + label, 'success');
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error('切换分辨率失败:', error);
|
logger.error('切换分辨率失败:', error);
|
||||||
showNotification('切换分辨率失败,摄像头可能不支持该分辨率', 'error');
|
showNotification('切换分辨率失败,摄像头可能不支持该分辨率', 'error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -835,10 +838,10 @@ class CallStateManager {
|
|||||||
}
|
}
|
||||||
params.encodings[0].maxBitrate = maxBitrate;
|
params.encodings[0].maxBitrate = maxBitrate;
|
||||||
sender.setParameters(params);
|
sender.setParameters(params);
|
||||||
console.log(`Updated maxBitrate to ${maxBitrate} for ${pid || 'self'}`);
|
logger.debug(`Updated maxBitrate to ${maxBitrate} for ${pid || 'self'}`);
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error('Error updating maxBitrate:', error);
|
logger.error('Error updating maxBitrate:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -865,7 +868,7 @@ class CallStateManager {
|
|||||||
this.updateRemoteMedia({ isSpeaking });
|
this.updateRemoteMedia({ isSpeaking });
|
||||||
}
|
}
|
||||||
async endCall() {
|
async endCall() {
|
||||||
console.log(`endCall called. Role: ${this.role}`);
|
logger.debug(`endCall called. Role: ${this.role}`);
|
||||||
await this.hangUp();
|
await this.hangUp();
|
||||||
}
|
}
|
||||||
async joinCall(connectionId) {
|
async joinCall(connectionId) {
|
||||||
@@ -898,7 +901,7 @@ class CallStateManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error('Error detecting network quality:', error);
|
logger.error('Error detecting network quality:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
startActivityDetection(stream, { isLocal = false } = {}) {
|
startActivityDetection(stream, { isLocal = false } = {}) {
|
||||||
@@ -936,10 +939,10 @@ class CallStateManager {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
detectActivity();
|
detectActivity();
|
||||||
console.log(`${isLocal ? 'Local' : 'Remote'} activity detection started`);
|
logger.debug(`${isLocal ? 'Local' : 'Remote'} activity detection started`);
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error(`Error starting ${isLocal ? 'local' : 'remote'} activity detection:`, error);
|
logger.error(`Error starting ${isLocal ? 'local' : 'remote'} activity detection:`, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
startNetworkQualityDetection() {
|
startNetworkQualityDetection() {
|
||||||
@@ -958,7 +961,7 @@ class CallStateManager {
|
|||||||
userId: this.state.session.localUser.id,
|
userId: this.state.session.localUser.id,
|
||||||
...this.state.session.localUser.mediaState
|
...this.state.session.localUser.mediaState
|
||||||
};
|
};
|
||||||
console.log('[WebSocket Emit] media-state-changed:', payload);
|
logger.debug('[WebSocket Emit] media-state-changed:', payload);
|
||||||
if (this.renderstreaming) {
|
if (this.renderstreaming) {
|
||||||
this.renderstreaming.sendMessage({
|
this.renderstreaming.sendMessage({
|
||||||
type: 'media-state-changed',
|
type: 'media-state-changed',
|
||||||
@@ -967,7 +970,7 @@ class CallStateManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
async showStatsMessage() {
|
async showStatsMessage() {
|
||||||
console.log('Showing stats message');
|
logger.debug('Showing stats message');
|
||||||
await this.detectNetworkQuality();
|
await this.detectNetworkQuality();
|
||||||
this.statsInterval = setInterval(async () => {
|
this.statsInterval = setInterval(async () => {
|
||||||
if (!this.renderstreaming) {
|
if (!this.renderstreaming) {
|
||||||
@@ -980,19 +983,19 @@ class CallStateManager {
|
|||||||
}
|
}
|
||||||
const statsSummary = summarizeInboundStats(stats);
|
const statsSummary = summarizeInboundStats(stats);
|
||||||
const statsLog = buildStatsLogPayload(this.state.session.remoteUser.networkQuality, statsSummary);
|
const statsLog = buildStatsLogPayload(this.state.session.remoteUser.networkQuality, statsSummary);
|
||||||
console.log('=== WebRTC Statistics ===');
|
logger.debug('=== WebRTC Statistics ===');
|
||||||
console.log(`Network Quality: ${statsLog.networkQuality}`);
|
logger.debug(`Network Quality: ${statsLog.networkQuality}`);
|
||||||
console.log('Video Stats:', statsLog.video);
|
logger.debug('Video Stats:', statsLog.video);
|
||||||
console.log('Audio Stats:', statsLog.audio);
|
logger.debug('Audio Stats:', statsLog.audio);
|
||||||
console.log('========================');
|
logger.debug('========================');
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error('Error showing stats message:', error);
|
logger.error('Error showing stats message:', error);
|
||||||
}
|
}
|
||||||
}, 5000);
|
}, 5000);
|
||||||
}
|
}
|
||||||
clearStatsMessage() {
|
clearStatsMessage() {
|
||||||
console.log('Clearing stats message');
|
logger.debug('Clearing stats message');
|
||||||
if (this.statsInterval) {
|
if (this.statsInterval) {
|
||||||
clearInterval(this.statsInterval);
|
clearInterval(this.statsInterval);
|
||||||
this.statsInterval = null;
|
this.statsInterval = null;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user