【m】占位重构完成
This commit is contained in:
@@ -137,108 +137,106 @@ class CallStateManager {
|
||||
|
||||
// 如果是开启视频,重新获取摄像头资源
|
||||
if (mediaType === 'video' && value) {
|
||||
if (this.state.localStream) {
|
||||
// 停止当前的媒体流
|
||||
try {
|
||||
// 只获取新的视频轨道,不干扰正在工作的音频
|
||||
const newVideoStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: false });
|
||||
const newVideoTrack = newVideoStream.getVideoTracks()[0];
|
||||
|
||||
if (!newVideoTrack) {
|
||||
throw new Error('Failed to get video track');
|
||||
}
|
||||
|
||||
// 更新本地流中的视频轨道(替换旧的已停止的轨道)
|
||||
if (this.state.localStream) {
|
||||
this.state.localStream.getTracks().forEach(track => track.stop());
|
||||
const oldVideoTracks = this.state.localStream.getVideoTracks();
|
||||
oldVideoTracks.forEach(track => {
|
||||
track.stop();
|
||||
this.state.localStream.removeTrack(track);
|
||||
});
|
||||
this.state.localStream.addTrack(newVideoTrack);
|
||||
} else {
|
||||
// 本地流不存在时(不应该发生),使用新流
|
||||
this.state.localStream = newVideoStream;
|
||||
}
|
||||
this.state.localStream = null;
|
||||
}
|
||||
// 请求摄像头权限并获取媒体流
|
||||
this.state.localStream = await navigator.mediaDevices.getUserMedia({
|
||||
video: true,
|
||||
audio: true
|
||||
});
|
||||
await this.getLocalStream();
|
||||
|
||||
// 更新WebRTC连接中的媒体轨道
|
||||
if (this.renderstreaming) {
|
||||
console.log('Updating media tracks in WebRTC connection');
|
||||
// 更新WebRTC连接中的视频轨道
|
||||
if (this.renderstreaming) {
|
||||
console.log('Updating video track in WebRTC connection');
|
||||
|
||||
// 获取所有收发器
|
||||
const transceivers = this.renderstreaming.getTransceivers();
|
||||
console.log('All transceivers:', transceivers);
|
||||
if (this.role === 'host') {
|
||||
// Host端:需要遍历所有participant的peer来替换视频轨道
|
||||
const participantIds = Object.keys(this.state.remoteStreams);
|
||||
for (const participantId of participantIds) {
|
||||
const transceivers = this.renderstreaming.getTransceivers(participantId);
|
||||
if (!transceivers) continue;
|
||||
|
||||
// 查找现有的视频和音频收发器
|
||||
const videoTransceivers = transceivers.filter(t => {
|
||||
return t.sender && t.sender.track && t.sender.track.kind === 'video';
|
||||
});
|
||||
console.log('Found video transceivers:', videoTransceivers);
|
||||
const videoTransceivers = transceivers.filter(t =>
|
||||
t.sender && t.sender.track && t.sender.track.kind === 'video'
|
||||
);
|
||||
|
||||
const audioTransceivers = transceivers.filter(t => {
|
||||
return t.sender && t.sender.track && t.sender.track.kind === 'audio';
|
||||
});
|
||||
console.log('Found audio transceivers:', audioTransceivers);
|
||||
|
||||
// 获取新的视频和音频轨道
|
||||
const videoTracks = this.state.localStream.getVideoTracks();
|
||||
console.log('New video tracks:', videoTracks);
|
||||
|
||||
const audioTracks = this.state.localStream.getAudioTracks();
|
||||
console.log('New audio tracks:', audioTracks);
|
||||
|
||||
|
||||
// 更新音频轨道
|
||||
if (audioTracks.length > 0) {
|
||||
const newAudioTrack = audioTracks[0];
|
||||
console.log('Using new audio track:', newAudioTrack);
|
||||
|
||||
if (audioTransceivers.length > 0) {
|
||||
// 替换现有的音频轨道
|
||||
for (const transceiver of audioTransceivers) {
|
||||
try {
|
||||
console.log('Replacing audio track in transceiver:', transceiver);
|
||||
await transceiver.sender.replaceTrack(newAudioTrack);
|
||||
console.log('Successfully replaced audio track');
|
||||
} catch (error) {
|
||||
console.error('Error replacing audio track:', error);
|
||||
if (videoTransceivers.length > 0) {
|
||||
for (const transceiver of videoTransceivers) {
|
||||
try {
|
||||
await transceiver.sender.replaceTrack(newVideoTrack);
|
||||
console.log(`Replaced video track for participant ${participantId}`);
|
||||
} catch (error) {
|
||||
console.error(`Error replacing video track for ${participantId}:`, error);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 没有视频收发器,添加新的
|
||||
try {
|
||||
this.renderstreaming.addTransceiver(newVideoTrack, { direction: 'sendonly' }, participantId);
|
||||
console.log(`Added new video transceiver for participant ${participantId}`);
|
||||
} catch (error) {
|
||||
console.error(`Error adding video transceiver for ${participantId}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
// 设置编解码器偏好
|
||||
setTimeout(() => { this.setCodecPreferences(participantId); }, 100);
|
||||
}
|
||||
} else {
|
||||
// 添加新的音频收发器
|
||||
try {
|
||||
console.log('Adding new audio transceiver');
|
||||
const transceiver = this.renderstreaming.addTransceiver(newAudioTrack, { direction: 'sendonly' });
|
||||
console.log('Added new audio transceiver:', transceiver);
|
||||
} catch (error) {
|
||||
console.error('Error adding new audio transceiver:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 更新视频轨道
|
||||
if (videoTracks.length > 0) {
|
||||
const newVideoTrack = videoTracks[0];
|
||||
console.log('Using new video track:', newVideoTrack);
|
||||
// Participant端:使用单一peer
|
||||
const transceivers = this.renderstreaming.getTransceivers();
|
||||
if (transceivers) {
|
||||
const videoTransceivers = transceivers.filter(t =>
|
||||
t.sender && t.sender.track && t.sender.track.kind === 'video'
|
||||
);
|
||||
|
||||
if (videoTransceivers.length > 0) {
|
||||
// 替换现有的视频轨道
|
||||
for (const transceiver of videoTransceivers) {
|
||||
try {
|
||||
console.log('Replacing video track in transceiver:', transceiver);
|
||||
await transceiver.sender.replaceTrack(newVideoTrack);
|
||||
console.log('Successfully replaced video track');
|
||||
} catch (error) {
|
||||
console.error('Error replacing video track:', error);
|
||||
if (videoTransceivers.length > 0) {
|
||||
for (const transceiver of videoTransceivers) {
|
||||
try {
|
||||
await transceiver.sender.replaceTrack(newVideoTrack);
|
||||
console.log('Successfully replaced video track');
|
||||
} catch (error) {
|
||||
console.error('Error replacing video track:', error);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
this.renderstreaming.addTransceiver(newVideoTrack, { direction: 'sendonly' });
|
||||
console.log('Added new video transceiver');
|
||||
} catch (error) {
|
||||
console.error('Error adding video transceiver:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 添加新的视频收发器
|
||||
try {
|
||||
console.log('Adding new video transceiver');
|
||||
const transceiver = this.renderstreaming.addTransceiver(newVideoTrack, { direction: 'sendonly' });
|
||||
console.log('Added new video transceiver:', transceiver);
|
||||
} catch (error) {
|
||||
console.error('Error adding new video transceiver:', error);
|
||||
}
|
||||
setTimeout(() => { this.setCodecPreferences(); }, 100);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新状态和通知UI
|
||||
this.state.session.localUser.mediaState.video = true;
|
||||
this.notify({ type: 'LOCAL_STREAM_OBTAINED', stream: this.state.localStream });
|
||||
this.notify({ type: 'LOCAL_MEDIA_CHANGE', mediaType: 'video', value: true });
|
||||
this.emitMediaStateChange();
|
||||
this.startLocalActivityDetection();
|
||||
|
||||
|
||||
// 延迟设置编解码器偏好,确保收发器已完全创建
|
||||
setTimeout(() => {
|
||||
this.setCodecPreferences();
|
||||
}, 100);
|
||||
} catch (error) {
|
||||
console.error('Error reopening video:', error);
|
||||
this.state.session.localUser.mediaState.video = false;
|
||||
this.notify({ type: 'LOCAL_MEDIA_CHANGE', mediaType: 'video', value: false });
|
||||
}
|
||||
} else {
|
||||
// 直接更新媒体状态
|
||||
@@ -481,9 +479,9 @@ class CallStateManager {
|
||||
}
|
||||
} else if (data.type === 'media-state-changed') {
|
||||
// 处理媒体状态变化
|
||||
console.log('收到媒体状态变化:', data.data);
|
||||
// 更新远程用户的媒体状态
|
||||
this.updateRemoteMedia(data.data);
|
||||
console.log('收到媒体状态变化:', data.data, 'from participant:', data.participantId);
|
||||
// 更新远程用户的媒体状态,传递participantId以便精准定位
|
||||
this.updateRemoteMedia(data.data, data.participantId);
|
||||
} else if (data.type === 'user-info') {
|
||||
// 处理用户信息更新
|
||||
console.log('收到用户信息:', data.data);
|
||||
@@ -601,12 +599,12 @@ class CallStateManager {
|
||||
|
||||
|
||||
// 更新远端媒体状态 (由 WebSocket 触发)
|
||||
updateRemoteMedia(mediaState) {
|
||||
updateRemoteMedia(mediaState, participantId) {
|
||||
this.state.session.remoteUser.mediaState = {
|
||||
...this.state.session.remoteUser.mediaState,
|
||||
...mediaState
|
||||
};
|
||||
this.notify({ type: 'REMOTE_MEDIA_CHANGE', mediaState });
|
||||
this.notify({ type: 'REMOTE_MEDIA_CHANGE', mediaState, participantId });
|
||||
// 通知UI更新用户列表
|
||||
this.notify({ type: 'USER_LIST_UPDATE', localUser: this.state.session.localUser, remoteUser: this.state.session.remoteUser });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user