COMMIT EXPLAINED · PPI-1290 · c7ad8cb4

AI 목소리가 밀릴 때,
일감을 줄이고 지연을 살펴봅니다.

마지막 업데이트 2026-09-14

불필요한 음성 처리를 덜어내고, 지연의 단서를 기록·재현하는 1차 대응입니다.

17개 파일 · +3,284 / −87 · 부모 4df55024 → c7ad8cb4
큰 그림 · 입력과 출력을 나눠서 보기
아이의 마이크로컬 입력
필요한 처리만 통과꺼진 EQ·압축·리미터는 생성하지 않음
AI 입력진행자 전달·녹음용 분기도 유지
AI 음성LiveKit 원격 수신
수신·재생 시계 감시지연 의심 로그 추가 · 영어 가드 OFF
아이의 스피커실제 출력 시점은 직접 측정 못함
단말 상태 → 저전력 의심 로그테스트 모드 → 오디오 부하 재현 도구
자동 재생 리셋은 기본 OFF. 이 커밋만으로 iPad 음성 밀림이 해결됐다고 확정할 수는 없습니다.
01 · 실제 동작 변경

꺼진 장치를 길에서 뺍니다

이전 · 처리 설정이 모두 OFF여도
게이트EQ ×3압축·제한출력
이후 · 처리 설정이 모두 OFF라면
게이트바로 연결출력

설정상 무효화하던 처리 노드를 이제 아예 만들지 않습니다. LiveKit에서는 Realtime 음성용 영어 감지도 끕니다.

무엇은 유지되나요?

켜진 처리 단계는 기존 순서대로 연결합니다. 게이트, 출력 gain, 원본 analyser 분기, AI 입력 차단 분기와 진행자 전달·녹음용 분기는 유지됩니다.

영어 가드는 저성능 기기가 아니고, 실제 음성 런타임이 Realtime이며, 설정도 ON일 때만 활성화됩니다. iPad만으로 제한한 변경은 아닙니다.

근거: LiveKitAudioChainProcessor의 단계별 노드 생성·연결 변경, effectiveEnglishGuardEnabledisRealtimeMode 조건 추가.

02 · 관측 추가

절전 상태의 흔적을 남깁니다

≈30화면 프레임 / 초
절전 의심로그로 기록

화면 갱신 간격에서 저전력 모드의 단서를 찾습니다. 절전 설정을 읽거나 바꾸는 기능은 아닙니다.

측정 방식과 한계

첫 샘플을 바로 수집하고, 각 수집 뒤 30초를 기다립니다. 60개 프레임 간격에서 p10 ≥ 28ms, 중앙값 ≤ 40ms이면 의심으로 분류합니다. 숨겨진 탭에서는 샘플 시작을 건너뜁니다.

게스트 세션에서 활성화되며 iPad에만 한정되지 않습니다. 기존 아바타 공유 AudioContext의 지연·상태도 함께 읽지만, 관측을 위해 새 AudioContext를 생성하거나 resume하지 않습니다.

LOW_POWER_PROBE는 휴리스틱 로그입니다. 실제 절전 모드 여부와 신고된 음성 밀림의 관계는 실기기·세션 증거로 대조해야 합니다.

03 · 감시 + 선택적 리셋

계속 밀리면 표시합니다

1초샘플 간격
400ms기본 의심 기준
3회연속 초과
기본 OFF의심 로그만 기록
선택 ON오디오 요소 재연결 시도

재생 시계의 뒤처짐과 수신 버퍼의 평균 지연을 더합니다. 스피커 자체에서만 생기는 지연은 놓칠 수 있습니다.

리셋 조건·관측 범위

AI 참가자의 오디오 트랙 하나를 감시하며, 구독 해제·연결 종료·정리 시 멈춥니다. 일시정지, 통계로 확인되는 수신 없는 구간은 제외하고 재연결 때 기준점을 다시 잡습니다.

livekitPlayoutReset=on일 때만 detach → attach 후 출력 차단 정책을 다시 적용합니다. 리셋 간격은 최소 10초, 세션당 최대 5회이며 트랙 재구독 후에도 제한이 이어집니다. 실제 지연 해소 효과는 별도 검증 대상입니다.

설정 우선순위는 URL 쿼리 → localStorage → 기본값입니다. livekitPlayoutDriftMs는 100~5,000ms 범위에서 지정할 수 있습니다.

currentTimeinbound-rtp만 관측합니다. 함께 남기는 입력 AudioContext의 outputLatency는 AI 출력 경로의 직접 지연값이 아닙니다.

04 · 테스트 모드 전용

일부러 바쁘게 만들어 봅니다

오디오 렌더 콜백의 목표 점유율
0%100% · 시간 예산150%

AudioContext를 쌓거나 오디오 처리 스레드에 부하를 줍니다. 같은 지연이 나타나는지 실험할 도구입니다.

추가된 조작과 정리

빈 AudioContext 또는 무음 oscillator를 가진 Context를 추가하고 한꺼번에 닫을 수 있습니다. 별도 AudioWorklet의 busy loop로 부하를 조절하며 실제 초당 호출 수를 기대치와 비교합니다.

설정 퍼센트는 부하 목표치이지 실측 CPU 사용률이 아닙니다. Context가 멈추거나 보고가 2.5초 이상 끊기면 이전 호출 수를 비웁니다. 종료·언마운트 시 생성한 리소스를 정리합니다.

테스트 모드에서만 생성·부하 시작이 허용됩니다. 이 도구의 추가가 기존 서비스에 AudioContext 누수가 존재한다는 증거는 아닙니다.

어디까지 확인된 커밋인가요?

변경 범위는 웹 게스트 세션·음성 처리·디버그 UI입니다. 이 설명은 지정 커밋과 부모의 차이를 기준으로 작성했습니다.

검증 상태 보기

커밋에는 처리 체인의 전체 OFF·부분 ON 연결, 저전력 판정·로그 기록·정리, 지연 계산·리셋 제한·관측 한계, 부하 도구의 수명·오류·보고 만료를 다루는 테스트 5개 파일이 추가돼 있습니다.

디버그 패널 Storybook에는 대기·Context 누적·생성 오류·렌더 부하 초과·인터럽션·미지원 상태의 6개 fixture가 있습니다. 테스트 스크립트에는 우회·지연 감시 테스트가 추가됐습니다.

이번 설명 작업에서 제품 테스트와 Storybook 빌드는 실행하지 않았습니다. 실기기 개선율, 운영 배포 상태, 스피커 출력 지연 해소 여부는 확인하지 않았습니다.

설명 HTML은 정적 구조·링크를 검사했습니다. 브라우저 연결 도구 오류로 실제 렌더링·반응형 화면·펼쳐보기 동작은 검증하지 못했습니다.

변경 파일 17개와 커밋 당시 소스 보기

원본 커밋 · 저장소 접근 권한이 필요할 수 있습니다.

[PPI-1290] feat: iPad AI 음성 밀림 1차 대응 — 영어 가드 LiveKit OFF·저전력 프로브·재생 지연 감시 (#1084)

  1. apps/web/entities/guest-page-session/model/use-audio-context-leak-harness.test.tsContext 누적·정리, 렌더 부하·오류·보고 만료 테스트 추가.
  2. apps/web/entities/guest-page-session/model/use-audio-context-leak-harness.ts테스트 모드의 Context 누적·무음 렌더·AudioWorklet 부하 도구 추가.
  3. apps/web/entities/guest-page-session/model/use-guest-page-session.ts영어 가드를 Realtime으로 제한하고 저전력 프로브·부하 도구 연결.
  4. apps/web/hooks/use-avatar-rms.ts기존 공유 AudioContext만 읽는 관측용 getter 추가.
  5. apps/web/hooks/use-low-power-mode-probe.lesson-log.test.ts저전력 의심·정상 로그가 수업 로그 버퍼에 남는지 검사.
  6. apps/web/hooks/use-low-power-mode-probe.test.ts프레임 통계 판정, 로깅, 비활성화·정리 테스트 추가.
  7. apps/web/hooks/use-low-power-mode-probe.ts프레임 간격 기반 저전력 의심 및 기존 Context 상태 로그 추가.
  8. apps/web/lib/voice-agent/livekit-audio-chain-processor.bypass.test.ts모두 OFF·모두 ON·부분 ON의 노드 생성과 연결 테스트 추가.
  9. apps/web/lib/voice-agent/livekit-audio-chain-processor.tsOFF 단계의 노드를 생성하지 않고 우회하며 실제 활성 단계 로그 추가.
  10. apps/web/lib/voice-agent/livekit-client-session.tsAI 원격 오디오 감시기 연결·해제와 선택적 재연결, 세션 공통 리셋 제한 연결.
  11. apps/web/lib/voice-agent/livekit-playout-drift-monitor.test.ts지연 산식, 관측 범위, 기본 OFF, 리셋 정책·감시 종료 테스트 추가.
  12. apps/web/lib/voice-agent/livekit-playout-drift-monitor.ts재생 시계·수신 버퍼 지연 감시와 설정·리셋 정책 추가.
  13. apps/web/lib/voice-agent/shared-input-audio-context.ts마이크 입력용 공유 Context를 생성 없이 읽는 getter 추가.
  14. apps/web/package.jsontest:livekit-vp에 처리 우회 및 재생 지연 감시 테스트 등록.
  15. apps/web/widgets/guest/guest-layout/ui/guest-debug-panel.stories.tsx실제 장치 없이 볼 수 있는 디버그 도구 상태 6개 추가.
  16. apps/web/widgets/guest/guest-layout/ui/guest-debug-panel.tsxContext·렌더 부하 조작과 상태 표시 추가, 패널 스크롤 영역 조정.
  17. apps/web/widgets/guest/guest-layout/ui/guest-layout.tsx세션의 부하 도구를 디버그 패널에 전달.