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 - 消息数据
|
||||
*/
|
||||
function handleChatMessage(data) {
|
||||
console.log('处理聊天:', data);
|
||||
logger.debug('处理聊天:', data);
|
||||
addMessage(data);
|
||||
|
||||
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();
|
||||
displayConnectionIds(data.connectionIds);
|
||||
} catch (error) {
|
||||
console.error('Error fetching connection IDs:', error);
|
||||
logger.error('Error fetching connection IDs:', error);
|
||||
showNotification('获取连接ID失败', 'error');
|
||||
}
|
||||
}
|
||||
@@ -164,7 +167,7 @@ function loadUserSettings() {
|
||||
document.getElementById('userAvatar').src = avatar;
|
||||
document.getElementById('avatarPreview').src = avatar;
|
||||
} catch (error) {
|
||||
console.error('Error loading user settings:', error);
|
||||
logger.error('Error loading user settings:', error);
|
||||
// 加载失败时使用默认头像
|
||||
const defaultAvatar = '/images/p1.png';
|
||||
document.getElementById('userAvatar').src = defaultAvatar;
|
||||
@@ -254,7 +257,7 @@ function handleAvatarUpload(event) {
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error uploading avatar:', error);
|
||||
logger.error('Error uploading avatar:', error);
|
||||
showNotification('头像上传失败,请重试', 'error');
|
||||
|
||||
// 上传失败时,使用默认头像
|
||||
|
||||
@@ -7,6 +7,9 @@ import {
|
||||
renderOnlineUsers
|
||||
} from './connect-directory.js';
|
||||
import { createProfileSettingsController } from './profile-settings.js';
|
||||
import { createLogger } from './logger.js';
|
||||
|
||||
const logger = createLogger('connectview');
|
||||
|
||||
let onWsStatusChange = null;
|
||||
let cachedOnlineUsers = [];
|
||||
@@ -45,9 +48,9 @@ export async function initWebSocket() {
|
||||
store.syncSocketUserInfo();
|
||||
updateWsStatus(true);
|
||||
await refreshOnlineUsers();
|
||||
console.log('WebSocket initialized from connectview');
|
||||
logger.debug('WebSocket initialized from connectview');
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize WebSocket:', error);
|
||||
logger.error('Failed to initialize WebSocket:', error);
|
||||
updateWsStatus(false);
|
||||
showNotification('WebSocket连接失败,请刷新页面重试', 'error');
|
||||
}
|
||||
@@ -62,7 +65,7 @@ async function refreshOnlineUsers(silent = true) {
|
||||
showNotification(`当前共有 ${cachedOnlineUsers.length} 个WebSocket用户在线`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching online users:', error);
|
||||
logger.error('Error fetching online users:', error);
|
||||
if (!silent) {
|
||||
showNotification('获取在线用户失败', 'error');
|
||||
}
|
||||
@@ -78,7 +81,7 @@ async function getAllConnectionIds() {
|
||||
updateConnectionIdList(connectionIds);
|
||||
updateOnlineUsersList(cachedOnlineUsers);
|
||||
} catch (error) {
|
||||
console.error('Error fetching connection IDs:', error);
|
||||
logger.error('Error fetching connection IDs:', error);
|
||||
showNotification('获取连接信息失败', 'error');
|
||||
}
|
||||
}
|
||||
@@ -104,7 +107,7 @@ function getCurrentUserId() {
|
||||
const settings = JSON.parse(localStorage.getItem('userSettings') || '{}');
|
||||
return settings.userId || settings.id || '';
|
||||
} catch (error) {
|
||||
console.error('Error parsing current user settings:', error);
|
||||
logger.error('Error parsing current user settings:', error);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import { createLogger } from './logger.js';
|
||||
|
||||
const logger = createLogger('invite');
|
||||
const DEFAULT_CALLER_NAME = '\u9080\u8bf7\u65b9';
|
||||
const DEFAULT_CALLER_AVATAR = '/images/p2.png';
|
||||
const DEFAULT_APPLY_REASON = '\u672a\u586b\u5199';
|
||||
@@ -127,7 +130,7 @@ export function createInviteController({
|
||||
targetUserId: pendingInvite.inviterUserId
|
||||
});
|
||||
} 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');
|
||||
return;
|
||||
}
|
||||
@@ -152,7 +155,7 @@ export function createInviteController({
|
||||
targetUserId: pendingInvite.inviterUserId
|
||||
});
|
||||
} 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
|
||||
} from './connectview.js';
|
||||
import { createInviteController } from './invite-controller.js';
|
||||
import { createLogger } from './logger.js';
|
||||
|
||||
const logger = createLogger('main');
|
||||
|
||||
let connectionId = '';
|
||||
let currentView = 'connect';
|
||||
@@ -43,10 +46,10 @@ async function switchToCallView(targetConnectionId) {
|
||||
renderer.renderHeaderTitle();
|
||||
callViewController.bindDomEvents();
|
||||
|
||||
console.log('Video call app initialized successfully');
|
||||
logger.debug('Video call app initialized successfully');
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Error initializing app:', error);
|
||||
logger.error('Error initializing app:', error);
|
||||
showNotification('初始化失败,请刷新页面重试', 'error');
|
||||
return false;
|
||||
}
|
||||
@@ -116,9 +119,9 @@ window.addEventListener('DOMContentLoaded', async () => {
|
||||
inviteController.showCallRequestDialog(invitePayload);
|
||||
}
|
||||
|
||||
console.log('SPA initialized, showing connect view');
|
||||
logger.debug('SPA initialized, showing connect view');
|
||||
} catch (error) {
|
||||
console.error('Error initializing SPA:', error);
|
||||
logger.error('Error initializing SPA:', error);
|
||||
showNotification('初始化失败,请刷新页面重试', 'error');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import { createLogger } from './logger.js';
|
||||
|
||||
const logger = createLogger('profile');
|
||||
const DEFAULT_AVATAR = '/images/p1.png';
|
||||
const MAX_AVATAR_SIZE = 2 * 1024 * 1024;
|
||||
const USER_ID_PREFIX = 'user_';
|
||||
@@ -100,7 +103,7 @@ export function createProfileSettingsController({ store, notify }) {
|
||||
updateUserName(settings.name || '\u6211');
|
||||
setAvatarPreview(settings.avatar || DEFAULT_AVATAR);
|
||||
} catch (error) {
|
||||
console.error('Error loading user settings:', error);
|
||||
logger.error('Error loading user settings:', error);
|
||||
setAvatarPreview(DEFAULT_AVATAR);
|
||||
}
|
||||
}
|
||||
@@ -152,7 +155,7 @@ export function createProfileSettingsController({ store, notify }) {
|
||||
saveSettings();
|
||||
notify('\u5934\u50cf\u4e0a\u4f20\u6210\u529f', 'success');
|
||||
} catch (error) {
|
||||
console.error('Error uploading avatar:', error);
|
||||
logger.error('Error uploading avatar:', error);
|
||||
setAvatarPreview(DEFAULT_AVATAR);
|
||||
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 { createLogger } from './logger.js';
|
||||
|
||||
const logger = createLogger('renderer-media');
|
||||
|
||||
export function getVideoResolution(track) {
|
||||
if (track && track.getSettings) {
|
||||
@@ -47,18 +50,18 @@ export function renderParticipantStreamMedia({
|
||||
if (!tile) {
|
||||
tile = createParticipantTile(connectionId, displayName);
|
||||
grid.appendChild(tile);
|
||||
console.log(`Created participant video tile for ${connectionId}`);
|
||||
logger.debug(`Created participant video tile for ${connectionId}`);
|
||||
}
|
||||
|
||||
const video = tile.querySelector('video');
|
||||
if (video && stream) {
|
||||
if (video.srcObject === stream) {
|
||||
console.log(`Same stream for participant ${connectionId}, ensuring playback`);
|
||||
video.play().catch(error => console.log('Auto-play prevented:', error.message));
|
||||
logger.debug(`Same stream for participant ${connectionId}, ensuring playback`);
|
||||
video.play().catch(error => logger.debug('Auto-play prevented:', error.message));
|
||||
} else {
|
||||
video.srcObject = stream;
|
||||
video.play().catch(error => console.log('Auto-play prevented:', error.message));
|
||||
console.log(`Set remote stream for participant tile ${connectionId}`);
|
||||
video.play().catch(error => logger.debug('Auto-play prevented:', error.message));
|
||||
logger.debug(`Set remote stream for participant tile ${connectionId}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,15 +89,15 @@ export function renderSingleRemoteStreamMedia({
|
||||
connectingOverlay
|
||||
}) {
|
||||
if (!remoteVideo || !stream) {
|
||||
console.error('Either remoteVideo element or stream is missing');
|
||||
logger.error('Either remoteVideo element or stream is missing');
|
||||
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) {
|
||||
console.log('Same stream object, track added - ensuring playback');
|
||||
remoteVideo.play().catch(error => console.log('Auto-play prevented:', error.message));
|
||||
logger.debug('Same stream object, track added - ensuring playback');
|
||||
remoteVideo.play().catch(error => logger.debug('Auto-play prevented:', error.message));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -103,7 +106,7 @@ export function renderSingleRemoteStreamMedia({
|
||||
remoteVideo.playsinline = true;
|
||||
remoteVideo.muted = false;
|
||||
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) {
|
||||
@@ -112,10 +115,10 @@ export function renderSingleRemoteStreamMedia({
|
||||
|
||||
const videoTracks = stream.getVideoTracks();
|
||||
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) {
|
||||
console.log('Audio-only stream, waiting for video track...');
|
||||
logger.debug('Audio-only stream, waiting for video track...');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -165,7 +168,7 @@ export function removeParticipantTile({
|
||||
video.srcObject = null;
|
||||
}
|
||||
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]');
|
||||
|
||||
@@ -23,6 +23,9 @@ import {
|
||||
renderParticipantStreamMedia,
|
||||
renderSingleRemoteStreamMedia
|
||||
} from './renderer-media.js';
|
||||
import { createLogger } from './logger.js';
|
||||
|
||||
const logger = createLogger('renderer');
|
||||
|
||||
const GRID_LAYOUT = {
|
||||
maxColumns: 3,
|
||||
@@ -317,13 +320,13 @@ class UIRenderer {
|
||||
this.elements.localVideo.srcObject = stream;
|
||||
this.elements.localVideo.autoplay = 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) {
|
||||
this.elements.disconnectedOverlay.classList.add('hidden');
|
||||
}
|
||||
} 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;
|
||||
if (!grid) return;
|
||||
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) {
|
||||
@@ -369,7 +372,7 @@ class UIRenderer {
|
||||
if (!grid) return;
|
||||
syncParticipantTileName(grid, participantId, 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() {
|
||||
console.log('Call ended');
|
||||
logger.debug('Call ended');
|
||||
clearParticipantGrid(this.elements.participantGrid);
|
||||
window.location.href = './endcall/endcall.html';
|
||||
}
|
||||
|
||||
renderParticipantLeft(connectionId) {
|
||||
console.log(`Participant left: ${connectionId}, updating UI`);
|
||||
logger.debug(`Participant left: ${connectionId}, updating UI`);
|
||||
removeParticipantTile({
|
||||
grid: this.elements.participantGrid,
|
||||
connectionId,
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { Signaling, WebSocketSignaling } from "../../module/signaling.js";
|
||||
import { createLogger } from './logger.js';
|
||||
|
||||
const logger = createLogger('signaling');
|
||||
|
||||
const INVITE_EVENT_NAMES = Object.freeze([
|
||||
'invite-call',
|
||||
@@ -72,7 +75,7 @@ function readStoredSocketUserInfo() {
|
||||
try {
|
||||
return JSON.parse(localStorage.getItem('userSettings') || '{}');
|
||||
} catch (error) {
|
||||
console.error('Error parsing user settings:', error);
|
||||
logger.error('Error parsing user settings:', error);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ import { AUDIO_CONFIG, VAD_CONFIG, VIDEO_ONLY_CONSTRAINT, buildVideoConstraints,
|
||||
import { buildStatsLogPayload, createAudioAnalyser, getAudioLevel } from './media-monitoring.js';
|
||||
import { bindInviteSocketEvents, buildSocketUserInfoPayload, createSignalingInstance, ensureSignalingStarted, getActiveSignalingInstance, sendInviteSignal, sendSocketUserInfo } from './signaling-session.js';
|
||||
import { getNetworkQualityFromSummary, summarizeInboundStats } from './webrtc-stats.js';
|
||||
import { createLogger } from './logger.js';
|
||||
|
||||
const logger = createLogger('store');
|
||||
class CallStateManager {
|
||||
constructor() {
|
||||
this.state = {
|
||||
@@ -55,11 +58,11 @@ class CallStateManager {
|
||||
}
|
||||
if (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) {
|
||||
console.error('Error loading user settings:', error);
|
||||
logger.error('Error loading user settings:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -69,9 +72,9 @@ class CallStateManager {
|
||||
}
|
||||
async getLocalStream() {
|
||||
try {
|
||||
console.log('Requesting camera permission...');
|
||||
logger.debug('Requesting camera permission...');
|
||||
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');
|
||||
}
|
||||
const videoConstraints = buildVideoConstraints(this._savedResolution);
|
||||
@@ -79,13 +82,13 @@ class CallStateManager {
|
||||
video: videoConstraints,
|
||||
audio: AUDIO_CONFIG
|
||||
});
|
||||
console.log('Stream obtained successfully:', stream);
|
||||
console.log('Video tracks:', stream.getVideoTracks());
|
||||
console.log('Audio tracks:', stream.getAudioTracks());
|
||||
logger.debug('Stream obtained successfully:', stream);
|
||||
logger.debug('Video tracks:', stream.getVideoTracks());
|
||||
logger.debug('Audio tracks:', stream.getAudioTracks());
|
||||
this.state.localStream = stream;
|
||||
this.state.session.localUser.mediaState.video = 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_MEDIA_CHANGE', mediaType: 'video', 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 });
|
||||
}
|
||||
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.audio = false;
|
||||
this.notify({ type: 'LOCAL_MEDIA_CHANGE', mediaType: 'video', value: false });
|
||||
@@ -133,7 +136,7 @@ class CallStateManager {
|
||||
this.startActivityDetection(this.state.localStream, { isLocal: true });
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error reopening video:', error);
|
||||
logger.error('Error reopening video:', error);
|
||||
this.state.session.localUser.mediaState.video = false;
|
||||
this._notifyLocalMediaChange('video', false);
|
||||
}
|
||||
@@ -162,7 +165,7 @@ class CallStateManager {
|
||||
if (!this.renderstreaming) {
|
||||
return;
|
||||
}
|
||||
console.log('Updating video track in WebRTC connection');
|
||||
logger.debug('Updating video track in WebRTC connection');
|
||||
if (this.role === 'host') {
|
||||
const participantIds = Object.keys(this.state.remoteStreams);
|
||||
for (const participantId of participantIds) {
|
||||
@@ -190,12 +193,12 @@ class CallStateManager {
|
||||
for (const transceiver of videoTransceivers) {
|
||||
try {
|
||||
await transceiver.sender.replaceTrack(newVideoTrack);
|
||||
console.log(participantId
|
||||
logger.debug(participantId
|
||||
? `Replaced video track for participant ${participantId}`
|
||||
: 'Successfully replaced video track');
|
||||
}
|
||||
catch (error) {
|
||||
console.error(participantId
|
||||
logger.error(participantId
|
||||
? `Error replacing video track for ${participantId}:`
|
||||
: 'Error replacing video track:', error);
|
||||
}
|
||||
@@ -205,14 +208,14 @@ class CallStateManager {
|
||||
try {
|
||||
if (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;
|
||||
}
|
||||
this.renderstreaming.addTransceiver(newVideoTrack, { direction: 'sendonly' });
|
||||
console.log('Added new video transceiver');
|
||||
logger.debug('Added new video transceiver');
|
||||
}
|
||||
catch (error) {
|
||||
console.error(participantId
|
||||
logger.error(participantId
|
||||
? `Error adding video transceiver for ${participantId}:`
|
||||
: 'Error adding video transceiver:', error);
|
||||
}
|
||||
@@ -262,10 +265,10 @@ class CallStateManager {
|
||||
this._signaling = signaling;
|
||||
this._inviteEventSignaling = bindInviteSocketEvents(this._signaling, this.socketEventHandlers, this._inviteEventSignaling);
|
||||
if (reused) {
|
||||
console.log('Signaling already connected, reusing existing instance');
|
||||
logger.debug('Signaling already connected, reusing existing instance');
|
||||
return this._signaling;
|
||||
}
|
||||
console.log('Signaling connected (WebSocket only, no room yet)');
|
||||
logger.debug('Signaling connected (WebSocket only, no room yet)');
|
||||
return this._signaling;
|
||||
}
|
||||
getActiveSignaling() {
|
||||
@@ -295,7 +298,7 @@ class CallStateManager {
|
||||
this.state.session.status = 'connecting';
|
||||
this.notify({ type: 'CALL_STATUS_CHANGE', status: 'connecting' });
|
||||
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) => {
|
||||
const checkStream = () => {
|
||||
if (this.state.localStream) {
|
||||
@@ -320,7 +323,7 @@ class CallStateManager {
|
||||
}
|
||||
_registerCallbacks() {
|
||||
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) {
|
||||
const tracks = this.state.localStream.getTracks();
|
||||
for (const track of tracks) {
|
||||
@@ -337,7 +340,7 @@ class CallStateManager {
|
||||
if (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.notify({ type: 'CALL_STATUS_CHANGE', status: 'ongoing' });
|
||||
@@ -349,7 +352,7 @@ class CallStateManager {
|
||||
}
|
||||
this.state.session.localUser.mediaState.audio = 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', {
|
||||
id: this.state.session.localUser.id,
|
||||
@@ -361,16 +364,16 @@ class CallStateManager {
|
||||
this.showStatsMessage();
|
||||
}
|
||||
else {
|
||||
console.error('Local stream is not available');
|
||||
logger.error('Local stream is not available');
|
||||
showNotification('本地视频流不可用', 'error');
|
||||
}
|
||||
};
|
||||
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.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') {
|
||||
const allParticipantIds = Object.keys(this.state.remoteStreams || {});
|
||||
for (const pid of allParticipantIds) {
|
||||
@@ -382,13 +385,13 @@ class CallStateManager {
|
||||
}
|
||||
};
|
||||
this.renderstreaming.onParticipantJoined = (participantId) => {
|
||||
console.log(`Participant joined: ${participantId}`);
|
||||
logger.debug(`Participant joined: ${participantId}`);
|
||||
this._upsertParticipant(participantId);
|
||||
this._notifyParticipantsUpdate();
|
||||
this.broadcastParticipantsList();
|
||||
};
|
||||
this.renderstreaming.onParticipantLeft = (participantId) => {
|
||||
console.log(`Participant left: ${participantId}, room still active`);
|
||||
logger.debug(`Participant left: ${participantId}, room still active`);
|
||||
this.updateRemoteUserStatus('offline');
|
||||
this.updateRemoteUserNetworkQuality('no_signal');
|
||||
showNotification('对方已离开通话', 'warning');
|
||||
@@ -428,14 +431,14 @@ class CallStateManager {
|
||||
}
|
||||
this.durationSynced = false;
|
||||
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) {
|
||||
try {
|
||||
await this.renderstreaming.deleteConnection();
|
||||
await this.renderstreaming.stop();
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error during hangUp:', error);
|
||||
logger.error('Error during hangUp:', error);
|
||||
}
|
||||
this.renderstreaming = null;
|
||||
}
|
||||
@@ -463,7 +466,7 @@ class CallStateManager {
|
||||
const isHost = this.role === 'host';
|
||||
const targetStream = this._getOrCreateRemoteStream(trackParticipantId, isHost);
|
||||
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]) {
|
||||
this._upsertParticipant(trackParticipantId);
|
||||
this._notifyParticipantsUpdate();
|
||||
@@ -500,7 +503,7 @@ class CallStateManager {
|
||||
const existingTracks = targetStream.getTracks().filter(existingTrack => existingTrack.kind === track.kind);
|
||||
existingTracks.forEach(existingTrack => {
|
||||
targetStream.removeTrack(existingTrack);
|
||||
console.log('Removed old track:', existingTrack.kind);
|
||||
logger.debug('Removed old track:', existingTrack.kind);
|
||||
});
|
||||
targetStream.addTrack(track);
|
||||
}
|
||||
@@ -512,13 +515,13 @@ class CallStateManager {
|
||||
connectionId: trackParticipantId,
|
||||
isHost
|
||||
});
|
||||
console.log('Notified UI about remote stream update');
|
||||
logger.debug('Notified UI about remote stream update');
|
||||
};
|
||||
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(() => {
|
||||
const nowHasVideo = targetStream.getVideoTracks().length > 0;
|
||||
console.log(`After delay, stream has video: ${nowHasVideo}`);
|
||||
logger.debug(`After delay, stream has video: ${nowHasVideo}`);
|
||||
notifyStreamUpdate();
|
||||
}, 200);
|
||||
return;
|
||||
@@ -526,7 +529,7 @@ class CallStateManager {
|
||||
notifyStreamUpdate();
|
||||
}
|
||||
_handleRenderStreamingMessage(data) {
|
||||
console.log('收到信令消息:', data);
|
||||
logger.debug('收到信令消息:', data);
|
||||
switch (data.type) {
|
||||
case 'chat-message':
|
||||
this._handleChatMessage(data);
|
||||
@@ -578,7 +581,7 @@ class CallStateManager {
|
||||
}
|
||||
}
|
||||
_handleMediaStateChangedMessage(data) {
|
||||
console.log('收到媒体状态更新:', data.data, 'from participant:', data.participantId);
|
||||
logger.debug('收到媒体状态更新:', data.data, 'from participant:', data.participantId);
|
||||
if (this.role === 'host') {
|
||||
if (data.participantId && this.state.participants[data.participantId]) {
|
||||
this._upsertParticipant(data.participantId, {
|
||||
@@ -600,12 +603,12 @@ class CallStateManager {
|
||||
if (data.participantId === this.selfParticipantId) {
|
||||
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._notifyParticipantsUpdate();
|
||||
}
|
||||
_handleUserInfoMessage(data) {
|
||||
console.log('收到用户信息:', data.data, 'from participant:', data.participantId);
|
||||
logger.debug('收到用户信息:', data.data, 'from participant:', data.participantId);
|
||||
if (!data.data) {
|
||||
return;
|
||||
}
|
||||
@@ -629,7 +632,7 @@ class CallStateManager {
|
||||
if (this.role === 'host' || !data.data) {
|
||||
return;
|
||||
}
|
||||
console.log('收到成员同步列表:', data.data);
|
||||
logger.debug('收到成员同步列表:', data.data);
|
||||
this.state.participants = omitParticipant(data.data, this.selfParticipantId);
|
||||
this._notifyParticipantsUpdate();
|
||||
this._syncCallDuration(data.callDuration);
|
||||
@@ -646,7 +649,7 @@ class CallStateManager {
|
||||
this.durationSynced = true;
|
||||
this._startDurationTimer();
|
||||
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() {
|
||||
if (this.durationInterval) {
|
||||
@@ -706,7 +709,7 @@ class CallStateManager {
|
||||
data: memberList,
|
||||
callDuration: this.state.session.duration
|
||||
});
|
||||
console.log('Broadcast participants list:', Object.keys(memberList));
|
||||
logger.debug('Broadcast participants list:', Object.keys(memberList));
|
||||
}
|
||||
setCodecPreferences(participantId) {
|
||||
const capabilities = RTCRtpSender.getCapabilities('video');
|
||||
@@ -744,10 +747,10 @@ class CallStateManager {
|
||||
t.setCodecPreferences(selectedCodecs);
|
||||
}
|
||||
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';
|
||||
}
|
||||
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) {
|
||||
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 },
|
||||
frameRate: { ideal: 30, max: 30 }
|
||||
});
|
||||
console.log(`分辨率已切换为 ${width}x${height}`);
|
||||
logger.debug(`分辨率已切换为 ${width}x${height}`);
|
||||
const maxBitrate = getTargetResolutionBitrate(height);
|
||||
this._applyMaxBitrate(maxBitrate);
|
||||
const userSettings = JSON.parse(localStorage.getItem('userSettings') || '{}');
|
||||
@@ -812,7 +815,7 @@ class CallStateManager {
|
||||
showNotification('已切换为 ' + label, 'success');
|
||||
}
|
||||
catch (error) {
|
||||
console.error('切换分辨率失败:', error);
|
||||
logger.error('切换分辨率失败:', error);
|
||||
showNotification('切换分辨率失败,摄像头可能不支持该分辨率', 'error');
|
||||
}
|
||||
}
|
||||
@@ -835,10 +838,10 @@ class CallStateManager {
|
||||
}
|
||||
params.encodings[0].maxBitrate = maxBitrate;
|
||||
sender.setParameters(params);
|
||||
console.log(`Updated maxBitrate to ${maxBitrate} for ${pid || 'self'}`);
|
||||
logger.debug(`Updated maxBitrate to ${maxBitrate} for ${pid || 'self'}`);
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error updating maxBitrate:', error);
|
||||
logger.error('Error updating maxBitrate:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -865,7 +868,7 @@ class CallStateManager {
|
||||
this.updateRemoteMedia({ isSpeaking });
|
||||
}
|
||||
async endCall() {
|
||||
console.log(`endCall called. Role: ${this.role}`);
|
||||
logger.debug(`endCall called. Role: ${this.role}`);
|
||||
await this.hangUp();
|
||||
}
|
||||
async joinCall(connectionId) {
|
||||
@@ -898,7 +901,7 @@ class CallStateManager {
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error detecting network quality:', error);
|
||||
logger.error('Error detecting network quality:', error);
|
||||
}
|
||||
}
|
||||
startActivityDetection(stream, { isLocal = false } = {}) {
|
||||
@@ -936,10 +939,10 @@ class CallStateManager {
|
||||
}
|
||||
};
|
||||
detectActivity();
|
||||
console.log(`${isLocal ? 'Local' : 'Remote'} activity detection started`);
|
||||
logger.debug(`${isLocal ? 'Local' : 'Remote'} activity detection started`);
|
||||
}
|
||||
catch (error) {
|
||||
console.error(`Error starting ${isLocal ? 'local' : 'remote'} activity detection:`, error);
|
||||
logger.error(`Error starting ${isLocal ? 'local' : 'remote'} activity detection:`, error);
|
||||
}
|
||||
}
|
||||
startNetworkQualityDetection() {
|
||||
@@ -958,7 +961,7 @@ class CallStateManager {
|
||||
userId: this.state.session.localUser.id,
|
||||
...this.state.session.localUser.mediaState
|
||||
};
|
||||
console.log('[WebSocket Emit] media-state-changed:', payload);
|
||||
logger.debug('[WebSocket Emit] media-state-changed:', payload);
|
||||
if (this.renderstreaming) {
|
||||
this.renderstreaming.sendMessage({
|
||||
type: 'media-state-changed',
|
||||
@@ -967,7 +970,7 @@ class CallStateManager {
|
||||
}
|
||||
}
|
||||
async showStatsMessage() {
|
||||
console.log('Showing stats message');
|
||||
logger.debug('Showing stats message');
|
||||
await this.detectNetworkQuality();
|
||||
this.statsInterval = setInterval(async () => {
|
||||
if (!this.renderstreaming) {
|
||||
@@ -980,19 +983,19 @@ class CallStateManager {
|
||||
}
|
||||
const statsSummary = summarizeInboundStats(stats);
|
||||
const statsLog = buildStatsLogPayload(this.state.session.remoteUser.networkQuality, statsSummary);
|
||||
console.log('=== WebRTC Statistics ===');
|
||||
console.log(`Network Quality: ${statsLog.networkQuality}`);
|
||||
console.log('Video Stats:', statsLog.video);
|
||||
console.log('Audio Stats:', statsLog.audio);
|
||||
console.log('========================');
|
||||
logger.debug('=== WebRTC Statistics ===');
|
||||
logger.debug(`Network Quality: ${statsLog.networkQuality}`);
|
||||
logger.debug('Video Stats:', statsLog.video);
|
||||
logger.debug('Audio Stats:', statsLog.audio);
|
||||
logger.debug('========================');
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error showing stats message:', error);
|
||||
logger.error('Error showing stats message:', error);
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
clearStatsMessage() {
|
||||
console.log('Clearing stats message');
|
||||
logger.debug('Clearing stats message');
|
||||
if (this.statsInterval) {
|
||||
clearInterval(this.statsInterval);
|
||||
this.statsInterval = null;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user