真实接口预热
This commit is contained in:
@ -27,6 +27,10 @@ function init() {
|
||||
});
|
||||
|
||||
animator.setMorphTargetAdapter(morphAdapter);
|
||||
animator.scene = sceneManager.scene;
|
||||
|
||||
// 把动画更新挂到 Babylon 渲染循环
|
||||
sceneManager.onBeforeRender = () => animator.tick();
|
||||
|
||||
// 导出全局变量供表情库使用
|
||||
window.animator = animator;
|
||||
@ -41,7 +45,7 @@ function init() {
|
||||
|
||||
// 加载3D模型
|
||||
sceneManager.loadModel('head_a01.glb',
|
||||
(meshes) => {
|
||||
async (meshes) => {
|
||||
showStatus("模型加载成功", "success");
|
||||
const totalTargets = morphAdapter.buildCache(meshes);
|
||||
|
||||
@ -50,43 +54,39 @@ function init() {
|
||||
} else {
|
||||
console.log(`✓ 构建缓存完成,共 ${totalTargets} 个形态键`);
|
||||
|
||||
// 预热着色器以避免首次动画卡顿
|
||||
console.log('预热着色器中...');
|
||||
morphAdapter.warmupShaders(sceneManager.scene);
|
||||
console.log('✓ 着色器预热完成');
|
||||
|
||||
// 播放120帧预热动画(4秒)
|
||||
console.log('预热渲染管线中...');
|
||||
const dummyFrames = [];
|
||||
const allBlendShapes = Object.keys(morphAdapter.morphTargetCache);
|
||||
console.log(`使用 ${allBlendShapes.length} 个blendshapes进行预热`);
|
||||
|
||||
for (let i = 0; i < 120; i++) {
|
||||
const blendShapes = {};
|
||||
const factor = Math.sin(i * 0.12) * 0.5 + 0.5;
|
||||
|
||||
allBlendShapes.forEach((name, index) => {
|
||||
const phase = (i + index * 5) * 0.18;
|
||||
const value = Math.sin(phase) * 0.5 + 0.5;
|
||||
if (value > 0.25) {
|
||||
blendShapes[name] = value * factor * 0.7;
|
||||
// 预热:直接调用生成动画流程(和用户点击按钮完全一样)
|
||||
showStatus("预热中...", "info");
|
||||
const apiUrl = document.getElementById('apiUrl').value;
|
||||
const streamEnabled = document.getElementById('streamEnabled')?.checked;
|
||||
console.log('预热 apiUrl:', apiUrl, 'stream:', streamEnabled);
|
||||
if (apiUrl) {
|
||||
try {
|
||||
// 和 generateAnimation 走完全一样的路径
|
||||
if (streamEnabled) {
|
||||
await generateAnimationStream('你好', apiUrl);
|
||||
} else {
|
||||
await generateAnimationBatch('你好', apiUrl);
|
||||
playAnimation();
|
||||
}
|
||||
});
|
||||
|
||||
dummyFrames.push({
|
||||
timeCode: i / 30,
|
||||
blendShapes: blendShapes
|
||||
});
|
||||
// 等播放完
|
||||
await new Promise(resolve => {
|
||||
const check = () => animator.isPlaying ? requestAnimationFrame(check) : resolve();
|
||||
check();
|
||||
});
|
||||
// 完全重置状态
|
||||
animator.stopAnimation();
|
||||
animator.loadAnimationFrames([]);
|
||||
animator.endStreaming();
|
||||
morphAdapter.resetAll();
|
||||
console.log('✓ 预热完成');
|
||||
} catch (e) {
|
||||
console.warn('预热失败:', e);
|
||||
}
|
||||
} else {
|
||||
console.warn('预热跳过: apiUrl 为空');
|
||||
}
|
||||
|
||||
animator.loadAnimationFrames(dummyFrames);
|
||||
animator.playAnimation();
|
||||
|
||||
setTimeout(() => {
|
||||
animator.stopAnimation();
|
||||
animator.loadAnimationFrames([]);
|
||||
console.log('✓ 渲染管线预热完成');
|
||||
}, 4000);
|
||||
showStatus("就绪", "success");
|
||||
}
|
||||
},
|
||||
(message) => {
|
||||
@ -95,6 +95,44 @@ function init() {
|
||||
);
|
||||
}
|
||||
|
||||
// 偷偷调接口预热 - 完全走一遍生成动画流程
|
||||
async function warmupWithApi() {
|
||||
console.log('=== warmupWithApi 开始 ===');
|
||||
const apiUrl = document.getElementById('apiUrl').value;
|
||||
console.log('apiUrl:', apiUrl);
|
||||
|
||||
try {
|
||||
// 完全走一遍 generateAnimationBatch 流程
|
||||
console.log('调用 generateAnimationBatch...');
|
||||
await generateAnimationBatch('你', apiUrl);
|
||||
console.log('generateAnimationBatch 完成, frames:', animator.animationFrames.length);
|
||||
|
||||
// 播放动画
|
||||
console.log('调用 playAnimation...');
|
||||
animator.playAnimation();
|
||||
|
||||
// 等待播放完成
|
||||
await new Promise(resolve => {
|
||||
const checkDone = () => {
|
||||
if (!animator.isPlaying) {
|
||||
resolve();
|
||||
} else {
|
||||
requestAnimationFrame(checkDone);
|
||||
}
|
||||
};
|
||||
requestAnimationFrame(checkDone);
|
||||
});
|
||||
|
||||
// 清空
|
||||
animator.loadAnimationFrames([]);
|
||||
morphAdapter.resetAll();
|
||||
|
||||
console.log('✓ 预热完成');
|
||||
} catch (e) {
|
||||
console.warn('预热失败:', e.message, e);
|
||||
}
|
||||
}
|
||||
|
||||
async function generateAnimation() {
|
||||
const text = document.getElementById('textInput').value.trim();
|
||||
const apiUrl = document.getElementById('apiUrl').value;
|
||||
@ -185,6 +223,10 @@ async function generateAnimationStream(text, apiUrl) {
|
||||
const handleMessage = (message) => {
|
||||
if (message.type === 'frame') {
|
||||
pendingFrames.push(message.frame);
|
||||
// 每100帧打印一次进度
|
||||
if (pendingFrames.length % 100 === 0) {
|
||||
console.log(`[前端] 已接收 ${pendingFrames.length} 帧, sentenceIndex=${message.frame.sentenceIndex}`);
|
||||
}
|
||||
flushFrames();
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user