This commit is contained in:
yinsx
2025-12-26 11:29:31 +08:00
parent 14bfdcbf51
commit 43ffe4486a
12 changed files with 196 additions and 40 deletions

View File

@ -12,7 +12,6 @@ class BabylonMorphTargetAdapter {
const mtm = mesh.morphTargetManager;
if (!mtm) return;
console.log(`网格 ${mesh.name}: ${mtm.numTargets} 个形态键`);
for (let i = 0; i < mtm.numTargets; i++) {
const mt = mtm.getTarget(i);
@ -25,14 +24,9 @@ class BabylonMorphTargetAdapter {
}
this.morphTargetCache[lowerName].push(mt);
totalTargets++;
if (i < 3) {
console.log(` ${mt.name} -> ${lowerName}`);
}
}
});
console.log(`总计: ${totalTargets} 个形态键映射`);
return totalTargets;
}

View File

@ -6,6 +6,7 @@ class BlendShapeAnimator {
this.animationShapeNames = [];
this.isPlaying = false;
this.currentFrameIndex = 0;
this.currentSentenceIndex = -1;
this.animationStartTime = 0;
this.idleAnimations = {};
this.blendShapeScale = config.blendShapeScale || 1.0;
@ -14,6 +15,7 @@ class BlendShapeAnimator {
this.streamingComplete = true;
this.streamingWaitStart = null;
this.streamingStallMs = 0;
this.sentenceTexts = []; // 句子文本列表
// 空闲动画参数
this.blinkParams = config.blinkParams || {
@ -254,6 +256,14 @@ class BlendShapeAnimator {
}
this.currentFrameIndex = targetFrameIndex;
// 更新当前句子显示
const sentenceIndex = currentFrame?.sentenceIndex ?? -1;
if (sentenceIndex !== this.currentSentenceIndex) {
this.currentSentenceIndex = sentenceIndex;
this._updateCurrentSentenceDisplay();
}
requestAnimationFrame(() => this._animateFrame());
}
@ -514,6 +524,21 @@ class BlendShapeAnimator {
return start + (end - start) * t;
}
_updateCurrentSentenceDisplay() {
const sentenceDiv = document.getElementById('currentSentence');
const sentenceText = document.getElementById('sentenceText');
if (!sentenceDiv || !sentenceText) return;
if (this.currentSentenceIndex >= 0 && this.currentSentenceIndex < this.sentenceTexts.length) {
sentenceDiv.style.display = 'block';
sentenceText.textContent = this.sentenceTexts[this.currentSentenceIndex];
console.log(`[前端调试] 显示句子 ${this.currentSentenceIndex}: ${this.sentenceTexts[this.currentSentenceIndex]}`);
} else {
sentenceDiv.style.display = 'none';
}
}
_applyEasing(t, type) {
switch(type) {
case 'easeOutQuad':

View File

@ -60,6 +60,11 @@
<div class="status" id="status"></div>
</div>
<!-- 当前播放句子显示(屏幕中央) -->
<div class="current-sentence" id="currentSentence" style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); padding: 20px 40px; background: rgba(0,0,0,0.7); border-radius: 10px; color: white; font-size: 24px; text-align: center; display: none; z-index: 1000; max-width: 80%; pointer-events: none;">
<div id="sentenceText"></div>
</div>
<div class="idle-controls">
<h2>空闲动画控制</h2>

View File

@ -141,6 +141,7 @@ async function generateAnimationStream(text, apiUrl) {
const flushBatchMs = 50;
const minStartFrames = Math.max(1, Math.round(animator.dataFps * (streamBufferMs / 1000)));
const frameBatchSize = Math.max(1, Math.round(animator.dataFps * (flushBatchMs / 1000)));
let sentenceTexts = []; // 存储句子文本
const flushFrames = (force = false) => {
if (pendingFrames.length === 0) {
@ -151,9 +152,7 @@ async function generateAnimationStream(text, apiUrl) {
}
const framesToFlush = pendingFrames.splice(0, pendingFrames.length);
animator.appendAnimationFrames(framesToFlush);
console.log(`Flushed ${framesToFlush.length} frames, total: ${animator.animationFrames.length}`);
if (!started && animator.animationFrames.length >= minStartFrames) {
console.log(`Starting animation with ${animator.animationFrames.length} frames (min: ${minStartFrames})`);
animator.playAnimation();
started = true;
}
@ -170,6 +169,12 @@ async function generateAnimationStream(text, apiUrl) {
const stageMessage = message.message || 'Streaming';
showStatus(stageMessage, 'info');
console.log('Stream status:', message);
// 保存句子文本并传递给动画器
if (message.sentence_texts) {
sentenceTexts = message.sentence_texts;
animator.sentenceTexts = sentenceTexts;
console.log('[前端调试] 接收到句子列表:', sentenceTexts);
}
return;
}