视频切换,切换三个场景,未实现场景人设切换
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 2m18s

This commit is contained in:
Song367 2025-08-04 17:36:30 +08:00
parent f176818155
commit c96c49ff3f
22 changed files with 333 additions and 57 deletions

104
server.js
View File

@ -85,10 +85,64 @@ app.delete('/api/messages/clear', async (req, res) => {
// 存储连接的客户端和他们的视频流状态 // 存储连接的客户端和他们的视频流状态
const connectedClients = new Map(); const connectedClients = new Map();
// 场景轮询系统
let currentSceneIndex = 0;
const scenes = [
{
name: '起床',
defaultVideo: '8-4-bd-2.mp4',
interactionVideo: '8-4-sh.mp4',
tag: 'wakeup'
},
{
name: '开车',
defaultVideo: '8-4-kc-bd.mp4', // 根据您的视频文件调整
interactionVideo: '8-4-kc-sh.mp4',
tag: 'driving'
},
{
name: '喝茶',
defaultVideo: '8-4-hc-bd.mp4',
interactionVideo: '8-4-hc-sh.mp4',
tag: 'tea'
}
];
// 获取当前场景
function getCurrentScene() {
return scenes[currentSceneIndex];
}
// 切换到下一个场景
function switchToNextScene() {
currentSceneIndex = (currentSceneIndex + 1) % scenes.length;
console.log(`切换到场景: ${getCurrentScene().name}`);
return getCurrentScene();
}
// 视频映射配置 - 动态更新
function getVideoMapping() {
const currentScene = getCurrentScene();
return {
'defaultVideo': currentScene.defaultVideo,
'interactionVideo': currentScene.interactionVideo,
'tag': currentScene.tag
};
}
// 默认视频流配置 - 动态获取
function getDefaultVideo() {
return getCurrentScene().defaultVideo;
}
let currentScene = getCurrentScene();
// 视频映射配置 // 视频映射配置
const videoMapping = { const videoMapping = {
// 'say-6s-m-e': '1-m.mp4', // 'say-6s-m-e': '1-m.mp4',
'default': 'chang.mp4', 'default': currentScene.defaultVideo,
'8-4-sh': currentScene.interactionVideo,
'tag': currentScene.tag
// 'say-5s-amplitude': '2.mp4', // 'say-5s-amplitude': '2.mp4',
// 'say-5s-m-e': '4.mp4', // 'say-5s-m-e': '4.mp4',
// 'say-5s-m-sw': 'd-0.mp4', // 'say-5s-m-sw': 'd-0.mp4',
@ -96,7 +150,7 @@ const videoMapping = {
}; };
// 默认视频流配置 // 默认视频流配置
const DEFAULT_VIDEO = 'chang.mp4'; const DEFAULT_VIDEO = currentScene.defaultVideo;
const INTERACTION_TIMEOUT = 10000; // 10秒后回到默认视频 const INTERACTION_TIMEOUT = 10000; // 10秒后回到默认视频
// 获取视频列表 // 获取视频列表
@ -115,13 +169,14 @@ app.get('/api/videos', (req, res) => {
// 获取视频映射 // 获取视频映射
app.get('/api/video-mapping', (req, res) => { app.get('/api/video-mapping', (req, res) => {
// videoMapping = getCurrentScene()
res.json({ mapping: videoMapping }); res.json({ mapping: videoMapping });
}); });
// 获取默认视频 // 获取默认视频
app.get('/api/default-video', (req, res) => { app.get('/api/default-video', (req, res) => {
res.json({ res.json({
defaultVideo: DEFAULT_VIDEO, defaultVideo: getDefaultVideo(),
autoLoop: true autoLoop: true
}); });
}); });
@ -131,7 +186,7 @@ io.on('connection', (socket) => {
console.log('用户连接:', socket.id); console.log('用户连接:', socket.id);
connectedClients.set(socket.id, { connectedClients.set(socket.id, {
socket: socket, socket: socket,
currentVideo: DEFAULT_VIDEO, currentVideo: getDefaultVideo(),
isInInteraction: false isInInteraction: false
}); });
@ -185,12 +240,12 @@ io.on('connection', (socket) => {
setTimeout(() => { setTimeout(() => {
console.log(`交互超时,用户 ${socket.id} 回到默认视频`); console.log(`交互超时,用户 ${socket.id} 回到默认视频`);
if (client) { if (client) {
client.currentVideo = DEFAULT_VIDEO; client.currentVideo = getDefaultVideo();
client.isInInteraction = false; client.isInInteraction = false;
} }
// 广播回到默认视频的指令 // 广播回到默认视频的指令
io.emit('video-stream-switched', { io.emit('video-stream-switched', {
videoFile: DEFAULT_VIDEO, videoFile: getDefaultVideo(),
type: 'default', type: 'default',
from: socket.id from: socket.id
}); });
@ -203,7 +258,7 @@ io.on('connection', (socket) => {
console.log('通话开始,用户:', socket.id); console.log('通话开始,用户:', socket.id);
const client = connectedClients.get(socket.id); const client = connectedClients.get(socket.id);
if (client) { if (client) {
client.currentVideo = DEFAULT_VIDEO; client.currentVideo = getDefaultVideo();
client.isInInteraction = false; client.isInInteraction = false;
} }
io.emit('call-started', { from: socket.id }); io.emit('call-started', { from: socket.id });
@ -262,15 +317,46 @@ io.on('connection', (socket) => {
console.log('用户请求回到默认视频:', socket.id); console.log('用户请求回到默认视频:', socket.id);
const client = connectedClients.get(socket.id); const client = connectedClients.get(socket.id);
if (client) { if (client) {
client.currentVideo = DEFAULT_VIDEO; client.currentVideo = getDefaultVideo();
client.isInInteraction = false; client.isInInteraction = false;
} }
socket.emit('switch-video-stream', { socket.emit('switch-video-stream', {
videoFile: DEFAULT_VIDEO, videoFile: getDefaultVideo(),
type: 'default' type: 'default'
}); });
}); });
// 处理用户关闭连接事件
socket.on('user-disconnect', () => {
console.log('用户主动关闭连接:', socket.id);
// 切换到下一个场景
const newScene = switchToNextScene();
console.log(`场景已切换到: ${newScene.name}`);
// 更新videoMapping
const newMapping = getVideoMapping();
videoMapping['default'] = newMapping.defaultVideo;
videoMapping['8-4-sh'] = newMapping.interactionVideo;
videoMapping['tag'] = newMapping.tag;
console.log('videoMapping已更新:', videoMapping);
// 清理客户端状态
const client = connectedClients.get(socket.id);
if (client) {
client.currentVideo = newMapping.defaultVideo;
client.isInInteraction = false;
}
// 广播场景切换事件给所有客户端
io.emit('scene-switched', {
scene: newScene,
mapping: newMapping,
from: socket.id
});
});
// 断开连接 // 断开连接
socket.on('disconnect', () => { socket.on('disconnect', () => {
console.log('用户断开连接:', socket.id); console.log('用户断开连接:', socket.id);

View File

@ -3,6 +3,7 @@
class AudioProcessor { class AudioProcessor {
constructor(options = {}) { constructor(options = {}) {
this.audioContext = null; this.audioContext = null;
this.stream = null; // 添加这一行
this.isRecording = false; this.isRecording = false;
this.audioChunks = []; this.audioChunks = [];
@ -311,22 +312,29 @@ class AudioProcessor {
} }
// 开始录音 // 开始录音
async startRecording() { async startRecording(existingStream = null) {
try { try {
const stream = await navigator.mediaDevices.getUserMedia({ // 如果有外部提供的音频流,使用它;否则获取新的
audio: { if (existingStream) {
sampleRate: 16000, this.stream = existingStream;
channelCount: 1, console.log('使用外部提供的音频流');
echoCancellation: true, } else {
noiseSuppression: true this.stream = await navigator.mediaDevices.getUserMedia({
} audio: {
}); sampleRate: 16000,
channelCount: 1,
echoCancellation: true,
noiseSuppression: true
}
});
console.log('获取新的音频流');
}
this.audioContext = new (window.AudioContext || window.webkitAudioContext)({ this.audioContext = new (window.AudioContext || window.webkitAudioContext)({
sampleRate: 16000 sampleRate: 16000
}); });
const source = this.audioContext.createMediaStreamSource(stream); const source = this.audioContext.createMediaStreamSource(this.stream);
const processor = this.audioContext.createScriptProcessor(4096, 1, 1); const processor = this.audioContext.createScriptProcessor(4096, 1, 1);
processor.onaudioprocess = (event) => { processor.onaudioprocess = (event) => {
@ -343,9 +351,13 @@ class AudioProcessor {
source.connect(processor); source.connect(processor);
processor.connect(this.audioContext.destination); processor.connect(this.audioContext.destination);
// 保存处理器引用以便后续清理
this.processor = processor;
this.source = source;
this.isRecording = true; this.isRecording = true;
this.onStatusUpdate('等待语音输入...', 'ready'); this.onStatusUpdate('等待语音输入...', 'ready');
// 在startRecording方法的最后添加 // 在startRecording方法的最后添加
if (this.adaptiveThreshold && this.noiseCalibrationSamples.length === 0) { if (this.adaptiveThreshold && this.noiseCalibrationSamples.length === 0) {
this.onStatusUpdate('正在校准背景噪音,请保持安静...', 'calibrating'); this.onStatusUpdate('正在校准背景噪音,请保持安静...', 'calibrating');
@ -364,6 +376,17 @@ class AudioProcessor {
stopRecording() { stopRecording() {
console.log('开始停止录音...'); console.log('开始停止录音...');
// 断开音频节点连接
if (this.source) {
this.source.disconnect();
this.source = null;
}
if (this.processor) {
this.processor.disconnect();
this.processor = null;
}
// 停止所有音频轨道 // 停止所有音频轨道
if (this.stream) { if (this.stream) {
this.stream.getTracks().forEach(track => { this.stream.getTracks().forEach(track => {
@ -400,6 +423,10 @@ class AudioProcessor {
this.consecutiveFramesCount = 0; this.consecutiveFramesCount = 0;
this.frameBuffer = []; this.frameBuffer = [];
// 重置校准状态,确保下次启动时重新校准
this.noiseCalibrationSamples = [];
this.isCalibrated = false;
this.onStatusUpdate('录音已完全停止', 'stopped'); this.onStatusUpdate('录音已完全停止', 'stopped');
console.log('录音已完全停止,所有资源已释放'); console.log('录音已完全停止,所有资源已释放');
} }

View File

@ -219,6 +219,67 @@
box-shadow: 0 6px 20px rgba(34, 197, 94, 0.5); box-shadow: 0 6px 20px rgba(34, 197, 94, 0.5);
} }
#startButton.connecting {
background: rgba(255, 193, 7, 0.9);
cursor: not-allowed;
}
#startButton.connecting:hover {
background: rgba(255, 193, 7, 0.9);
transform: none;
}
#startButton.calling {
background: rgba(255, 193, 7, 0.9);
animation: pulse 2s infinite;
}
#startButton.calling:hover {
background: rgba(255, 193, 7, 0.95);
transform: scale(1.05);
}
@keyframes pulse {
0% {
box-shadow: 0 4px 15px rgba(255, 193, 7, 0.3);
}
50% {
box-shadow: 0 6px 25px rgba(255, 193, 7, 0.6);
}
100% {
box-shadow: 0 4px 15px rgba(255, 193, 7, 0.3);
}
}
.audio-status {
position: absolute;
top: 20px;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 8px 16px;
border-radius: 20px;
font-size: 14px;
z-index: 1000;
transition: all 0.3s ease;
}
.audio-status.connecting {
background: rgba(255, 193, 7, 0.9);
color: #000;
}
.audio-status.connected {
background: rgba(40, 167, 69, 0.9);
color: white;
}
.audio-status.error {
background: rgba(220, 53, 69, 0.9);
color: white;
}
#startButton svg { #startButton svg {
width: 24px; width: 24px;
height: 24px; height: 24px;
@ -251,8 +312,8 @@
</header> </header>
<div class="main-content"> <div class="main-content">
<!-- 隐藏的音频状态显示 --> <!-- 音频状态显示 - 显示状态文本 -->
<div class="audio-status" style="display: none;"> <div class="audio-status">
<div class="status-indicator"> <div class="status-indicator">
<span id="audioStatus">未连接</span> <span id="audioStatus">未连接</span>
</div> </div>
@ -288,9 +349,22 @@
<!-- 控制按钮 - 悬浮在视频上方 --> <!-- 控制按钮 - 悬浮在视频上方 -->
<div class="controls"> <div class="controls">
<button id="startButton" class="btn btn-primary" title="开始通话"> <button id="startButton" class="btn btn-primary" title="开始通话">
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <!-- 默认通话图标 -->
<svg id="callIcon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z" fill="white"/> <path d="M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z" fill="white"/>
</svg> </svg>
<!-- 通话中图标(初始隐藏) -->
<svg id="callingIcon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" style="display: none;">
<circle cx="12" cy="12" r="3" fill="white">
<animate attributeName="r" values="3;5;3" dur="1.5s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="1;0.5;1" dur="1.5s" repeatCount="indefinite"/>
</circle>
<circle cx="12" cy="12" r="8" stroke="white" stroke-width="2" fill="none" opacity="0.6">
<animate attributeName="r" values="8;12;8" dur="2s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.6;0.2;0.6" dur="2s" repeatCount="indefinite"/>
</circle>
<path d="M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z" fill="white" opacity="0.8"/>
</svg>
</button> </button>
<button id="stopButton" class="btn btn-danger" disabled title="结束通话"> <button id="stopButton" class="btn btn-danger" disabled title="结束通话">
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">

View File

@ -9,6 +9,8 @@ class WebRTCChat {
constructor() { constructor() {
console.log('WebRTCChat 构造函数开始执行'); console.log('WebRTCChat 构造函数开始执行');
// 初始化历史消息(异步) // 初始化历史消息(异步)
this.initializeHistory(); this.initializeHistory();
@ -20,6 +22,7 @@ class WebRTCChat {
this.audioChunks = []; this.audioChunks = [];
this.videoMapping = {}; this.videoMapping = {};
this.defaultVideo = 'chang.mp4'; this.defaultVideo = 'chang.mp4';
this.interactionVideo = 'chang.mp4';
this.currentVideoTag = 'default'; this.currentVideoTag = 'default';
this.currentVideo = null; this.currentVideo = null;
this.videoStreams = new Map(); // 存储不同视频的MediaStream this.videoStreams = new Map(); // 存储不同视频的MediaStream
@ -147,6 +150,13 @@ class WebRTCChat {
this.logMessage('通话已开始', 'success'); this.logMessage('通话已开始', 'success');
this.startDefaultVideoStream(); this.startDefaultVideoStream();
}); });
// 场景切换处理
this.socket.on('scene-switched', (data) => {
this.logMessage(`场景已切换到: ${data.currentScene}`, 'info');
// 移除自动清除缓存和播放视频的逻辑
// 现在依赖页面刷新来处理缓存清除
});
} }
async initializeHistory() { async initializeHistory() {
@ -163,6 +173,8 @@ class WebRTCChat {
const response = await fetch('/api/video-mapping'); const response = await fetch('/api/video-mapping');
const data = await response.json(); const data = await response.json();
this.videoMapping = data.mapping; this.videoMapping = data.mapping;
this.interactionVideo = data.mapping['8-4-sh'];
this.defaultVideo = data.mapping["default"];
this.logMessage('视频映射加载成功', 'success'); this.logMessage('视频映射加载成功', 'success');
} catch (error) { } catch (error) {
this.logMessage('加载视频映射失败: ' + error.message, 'error'); this.logMessage('加载视频映射失败: ' + error.message, 'error');
@ -429,7 +441,8 @@ class WebRTCChat {
// 在应用初始化时预加载常用视频 // 在应用初始化时预加载常用视频
async preloadCommonVideos() { async preloadCommonVideos() {
// 获取所有可能需要的视频 // 获取所有可能需要的视频
const videosToPreload = new Set(['chang.mp4']); console.log("default video, interaction video", [this.defaultVideo, this.interactionVideo])
const videosToPreload = new Set([this.defaultVideo, this.interactionVideo]);
// 添加视频映射中的所有视频 // 添加视频映射中的所有视频
// Object.values(this.videoMapping).forEach(video => { // Object.values(this.videoMapping).forEach(video => {
@ -801,6 +814,9 @@ class WebRTCChat {
async startCall() { async startCall() {
try { try {
// 切换到通话中图标
this.switchToCallingIcon();
// 添加更详细的错误处理 // 添加更详细的错误处理
console.log('开始请求麦克风权限...'); console.log('开始请求麦克风权限...');
this.localStream = await navigator.mediaDevices.getUserMedia({ this.localStream = await navigator.mediaDevices.getUserMedia({
@ -810,8 +826,8 @@ class WebRTCChat {
console.log('麦克风权限获取成功'); console.log('麦克风权限获取成功');
await this.createPeerConnection(); await this.createPeerConnection();
this.startVoiceRecording() await this.startVoiceRecording();
// this.audioProcessor.startRecording()
this.startButton.disabled = true; this.startButton.disabled = true;
this.stopButton.disabled = false; this.stopButton.disabled = false;
@ -831,12 +847,25 @@ class WebRTCChat {
// 通知服务器通话开始 // 通知服务器通话开始
this.socket.emit('call-started'); this.socket.emit('call-started');
// 开始播放当前场景的默认视频
await this.startDefaultVideoStream();
} catch (error) { } catch (error) {
// 如果出错,恢复到默认图标
this.switchToDefaultIcon();
this.logMessage('无法访问麦克风: ' + error.message, 'error'); this.logMessage('无法访问麦克风: ' + error.message, 'error');
} }
} }
stopCall() { stopCall() {
// 恢复到默认图标
this.switchToDefaultIcon();
// 发送用户关闭连接事件到后端
if (this.socket && this.socket.connected) {
this.socket.emit('user-disconnect');
}
// 停止音频处理器 // 停止音频处理器
if (this.audioProcessor) { if (this.audioProcessor) {
this.audioProcessor.stopRecording(); this.audioProcessor.stopRecording();
@ -855,23 +884,59 @@ class WebRTCChat {
this.peerConnection = null; this.peerConnection = null;
} }
// 停止当前视频流 // 直接刷新页面清除所有缓存
console.log('通话已结束,正在刷新页面清除缓存...');
window.location.reload();
}
// 清除视频缓存的方法
clearVideoCache() {
// 清除视频元素缓存
if (this.recordedVideo) {
this.recordedVideo.src = '';
this.recordedVideo.srcObject = null;
this.recordedVideo.load(); // 重新加载空视频
// 暂停视频播放
this.recordedVideo.pause();
}
if (this.recordedVideoBuffer) {
this.recordedVideoBuffer.src = '';
this.recordedVideoBuffer.srcObject = null;
this.recordedVideoBuffer.load();
this.recordedVideoBuffer.pause();
}
// 清除视频流缓存
if (this.currentVideoStream) { if (this.currentVideoStream) {
this.currentVideoStream.getTracks().forEach(track => track.stop()); this.currentVideoStream.getTracks().forEach(track => track.stop());
this.currentVideoStream = null; this.currentVideoStream = null;
} }
this.recordedVideo.srcObject = null; // 清除视频流映射缓存
this.videoStreams.clear();
// 重置视频相关状态
this.currentVideo = null; this.currentVideo = null;
this.activeVideoElement = 'main';
this.videoSender = null;
this.startButton.disabled = false; this.logMessage('视频缓存已清除,视频已停止', 'info');
this.stopButton.disabled = true; }
// 添加清除API缓存的方法
async clearApiCache() {
// 重新加载视频映射
this.videoMapping = {};
await this.loadVideoMapping();
// 隐藏结束通话按钮 // 重新加载默认视频
this.stopButton.classList.remove('show'); await this.loadDefaultVideo();
this.updateAudioStatus('未连接', 'disconnected'); // 重新加载视频列表
this.logMessage('音频通话已结束,所有资源已释放', 'info'); await this.loadVideoList();
this.logMessage('API缓存已清除并重新加载', 'info');
} }
async createPeerConnection() { async createPeerConnection() {
@ -1041,16 +1106,12 @@ class WebRTCChat {
// 修改:使用音频处理器的语音录制功能 // 修改:使用音频处理器的语音录制功能
async startVoiceRecording() { async startVoiceRecording() {
const success = await this.audioProcessor.startRecording(); const success = await this.audioProcessor.startRecording(this.localStream);
if (success) { if (success) {
// this.startVoiceButton.disabled = true;
// this.stopVoiceButton.disabled = false;
// this.startVoiceButton.classList.add('recording');
// this.voiceStatus.textContent = '等待语音输入...';
this.logMessage('高级语音录制已启动', 'success'); this.logMessage('高级语音录制已启动', 'success');
} else { } else {
// this.voiceStatus.textContent = '录音启动失败'; this.logMessage('录音启动失败', 'error');
} }
} }
@ -1154,6 +1215,34 @@ class WebRTCChat {
this.logMessage(`视频流状态: ${JSON.stringify(status)}`, 'info'); this.logMessage(`视频流状态: ${JSON.stringify(status)}`, 'info');
return status; return status;
} }
// 添加图标切换方法
switchToCallingIcon() {
const callIcon = document.getElementById('callIcon');
const callingIcon = document.getElementById('callingIcon');
const startButton = this.startButton;
if (callIcon && callingIcon && startButton) {
callIcon.style.display = 'none';
callingIcon.style.display = 'block';
startButton.classList.add('calling');
startButton.title = '通话中...';
}
}
switchToDefaultIcon() {
const callIcon = document.getElementById('callIcon');
const callingIcon = document.getElementById('callingIcon');
const startButton = this.startButton;
if (callIcon && callingIcon && startButton) {
callIcon.style.display = 'block';
callingIcon.style.display = 'none';
startButton.classList.remove('calling');
startButton.title = '开始通话';
startButton.disabled = false;
}
}
async testAllVideoFiles() { async testAllVideoFiles() {
this.logMessage('开始测试所有视频文件...', 'info'); this.logMessage('开始测试所有视频文件...', 'info');

View File

@ -65,19 +65,19 @@ async function processAudioQueue() {
// 如果当前没有音频在播放,且队列中有音频 // 如果当前没有音频在播放,且队列中有音频
if (!isPlaying && audioQueue.length > 0) { if (!isPlaying && audioQueue.length > 0) {
const audioItem = audioQueue.shift(); const audioItem = audioQueue.shift();
const sayName = 'say-5s-m-sw' const sayName = '8-4-sh'
const targetVideo = 'd-0.mp4' const targetVideo = window.webrtcApp.interactionVideo
// 如果是第一个音频片段,触发视频切换 // 如果是第一个音频片段,触发视频切换
// if (isFirstChunk && sayName != window.webrtcApp.currentVideoTag && window.webrtcApp && window.webrtcApp.switchVideoWithReplaceTrack) { if (isFirstChunk && sayName != window.webrtcApp.currentVideoTag && window.webrtcApp && window.webrtcApp.switchVideoWithReplaceTrack) {
// try { try {
// console.log('--------------触发视频切换:', sayName); console.log('--------------触发视频切换:', sayName);
// window.webrtcApp.switchVideoWithReplaceTrack(targetVideo, 'audio', 'say-5s-m-sw'); window.webrtcApp.switchVideoWithReplaceTrack(targetVideo, 'audio', '8-4-sh');
// isFirstChunk = false; isFirstChunk = false;
// window.webrtcApp.currentVideoTag = sayName; window.webrtcApp.currentVideoTag = sayName;
// } catch (error) { } catch (error) {
// console.error('视频切换失败:', error); console.error('视频切换失败:', error);
// } }
// } }
await playAudioData(audioItem.audioData); await playAudioData(audioItem.audioData);
} else { } else {
// 等待一小段时间再检查 // 等待一小段时间再检查
@ -89,11 +89,11 @@ async function processAudioQueue() {
const text = 'default' const text = 'default'
// await new Promise(resolve => setTimeout(resolve, 500)); // await new Promise(resolve => setTimeout(resolve, 500));
console.log("音频结束------------------------", window.webrtcApp.currentVideoTag, isPlaying) console.log("音频结束------------------------", window.webrtcApp.currentVideoTag, isPlaying)
// if (window.webrtcApp.currentVideoTag != text) { if (window.webrtcApp.currentVideoTag != text) {
// isFirstChunk = true isFirstChunk = true
// window.webrtcApp.currentVideoTag = text window.webrtcApp.currentVideoTag = text
// window.webrtcApp.switchVideoWithReplaceTrack(window.webrtcApp.defaultVideo, 'audio', text); window.webrtcApp.switchVideoWithReplaceTrack(window.webrtcApp.defaultVideo, 'audio', text);
// } }
console.log('音频队列处理完成'); console.log('音频队列处理完成');
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
videos/8-4-bd-1.mp4 Normal file

Binary file not shown.

BIN
videos/8-4-bd-2.mp4 Normal file

Binary file not shown.

BIN
videos/8-4-bd.mp4 Normal file

Binary file not shown.

BIN
videos/8-4-hc-bd.mp4 Normal file

Binary file not shown.

BIN
videos/8-4-hc-sh.mp4 Normal file

Binary file not shown.

BIN
videos/8-4-kc-bd.mp4 Normal file

Binary file not shown.

BIN
videos/8-4-kc-sh.mp4 Normal file

Binary file not shown.

BIN
videos/8-4-sh.mp4 Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.