Stabilize runtime auth and E2E coverage
This commit is contained in:
parent
6a3e3b541c
commit
188e899394
133 changed files with 55987 additions and 6775 deletions
|
|
@ -59,10 +59,10 @@ function smoothMouthFromRMS(
|
|||
return prev + (target - prev) * alpha;
|
||||
}
|
||||
|
||||
/* ── analyser 없을 때 가짜 립싱크 (§ 명세: 텍스트/타이핑 기반 폴백) ──────
|
||||
외부에서 speakingProgress(0~1, 발화 타이핑 진행) 를 주면 그걸 따라가고,
|
||||
없으면 음절감 있는 의사 RMS 를 합성한다(과하지 않게). */
|
||||
function fakeMouthTarget(tSec: number, progress: number | null): number {
|
||||
/* ── analyser 없을 때의 립싱크 폴백 ─────────────────────────────────────
|
||||
외부에서 speakingProgress(0~1, 발화 타이핑 진행)를 명시적으로 줄 때만
|
||||
낮은 진폭으로 움직인다. 실제 음성 분석이 없으면 합성 발화처럼 보이지 않게 닫아 둔다. */
|
||||
function fallbackMouthTarget(tSec: number, progress: number | null): number {
|
||||
if (progress !== null) {
|
||||
// 타이핑 진행 중에만 입을 움직임. 진행이 멈추면(완료) 닫힘.
|
||||
if (progress >= 1) return 0;
|
||||
|
|
@ -72,17 +72,14 @@ function fakeMouthTarget(tSec: number, progress: number | null): number {
|
|||
const base = 0.18 + 0.42 * syl * jitter;
|
||||
return Math.min(0.85, base);
|
||||
}
|
||||
// progress 미제공: 차분한 의사 발화 (말하는 듯한 진폭)
|
||||
const a = 0.5 + 0.5 * Math.sin(tSec * 2 * Math.PI * 4.5);
|
||||
const b = 0.5 + 0.5 * Math.sin(tSec * 2 * Math.PI * 9.2 + 0.7);
|
||||
return Math.min(0.8, 0.15 + 0.45 * a * b);
|
||||
return 0;
|
||||
}
|
||||
|
||||
export interface AvatarMotionOptions {
|
||||
state: AvatarState;
|
||||
params: AffectParams;
|
||||
analyser: AnalyserNode | null;
|
||||
/** analyser 없을 때 가짜 립싱크용 타이핑 진행도 0~1 (null=의사 발화) */
|
||||
/** analyser 없을 때 선택적으로 쓰는 타이핑 진행도 0~1 */
|
||||
speakingProgress?: number | null;
|
||||
/** false 면 루프 정지(reduced-motion) — IDLE_FRAME 고정 */
|
||||
enabled: boolean;
|
||||
|
|
@ -188,14 +185,14 @@ export function useAvatarMotion({
|
|||
}
|
||||
}
|
||||
|
||||
// ── 4) 립싱크 (speaking 시만; analyser 우선, 없으면 폴백) ──
|
||||
// ── 4) 립싱크 (speaking 시만; analyser 우선, 없으면 정적 폴백) ──
|
||||
let mouth = mouthPrev;
|
||||
if (st === "speaking") {
|
||||
const a = analyserRef.current;
|
||||
if (a) {
|
||||
mouthPrev = smoothMouthFromRMS(a, audioBuf, mouthPrev, dtSec);
|
||||
} else {
|
||||
const target = fakeMouthTarget(tSec, progressRef.current ?? null);
|
||||
const target = fallbackMouthTarget(tSec, progressRef.current ?? null);
|
||||
const tau = 0.12;
|
||||
const alpha = 1 - Math.exp(-dtSec / tau);
|
||||
mouthPrev = mouthPrev + (target - mouthPrev) * alpha;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue