갤럭시 탭 S10 FE simulcast 인코딩 부하 검증 — 레이어별 로깅 + 1레이어 토글 검증 도구

마지막 업데이트 2026-07-22

맥락: S10 FE 카메라 simulcast 3레이어 인코딩이 단말 부하의 원인인지 검증 브랜치: test/simulcast-load 작성일: 2026-06-18

한 줄 요약

갤럭시 탭 S10 FE가 카메라를 simulcast 3레이어(저·중·고)로 동시 인코딩할 때 실제로 단말 부하가 걸리는지, 그리고 그 부하가 DECODE_OVERLOAD(영상 끊김)socket.io 업링크 stall(자동전환 미반영)과 연관 있는지를 정량 검증하기 위한 로깅 + 1레이어 토글use-mediasoup-producer.ts에 추가했다. 레이어별 프레임당 인코딩 시간·CPU 제한 여부·HW 가속 여부를 2초 주기로 기록하고, 테스트 모드 디버그 패널에서 1↔3 레이어를 즉시 전환해 같은 단말에서 A/B 비교한다.

배경 · 가설

아동 단말(S10 FE)은 수업 중 다음을 동시에 수행한다:

가설: 3레이어 인코딩이 단말 CPU/미디어 코덱 HW를 점유 → ① 활동 영상 디코드를 굶겨 DECODE_OVERLOAD 유발, ② 업링크 대역폭을 잡아먹어 socket.io ack 지연(업링크 stall)에 기여.

추가한 로깅 검증 신호

1. 인코딩 시작 시점 (1회) — [SIMULCAST-LOAD] Camera encoding config

레이어 구성, 원본 트랙 해상도/fps, 단말 식별 정보를 기록한다.

2. 주기 측정 (2초마다) — [SIMULCAST-LOAD] Camera encoder stats

producer.getStats()의 outbound-rtp 통계를 레이어(ssrc/rid)별로 읽고, totalEncodeTime·framesEncoded구간 증가분으로 프레임당 인코딩 시간을 계산한다(누적값 아님 → 실시간 부하).

필드부하 신호의미
cpuLimitedtrue레이어 중 하나라도 qualityLimitationReason === "cpu" → CPU 부족으로 화질 강등 (가장 확실한 부하 신호)
totalEncodeMsPerFrame값 ↑활성 레이어 전체의 프레임당 인코딩 시간 합(ms) = 단말 총 인코딩 부하 근사치
layers[].powerEfficientEncoderfalseHW 가속 미사용 = SW 인코딩 → CPU 부하 큼
layers[].encoderImplementationSW 이름libvpx·OpenH264 등이면 SW
layers[].fps목표 대비 ↓30 목표 대비 크게 낮으면 인코딩이 못 따라감
activeLayers현재 인코딩 중인 레이어 수 (토글 반영 확인용)
// 부하 걸린 상태 예시
[SIMULCAST-LOAD] Camera encoder stats {
  cpuLimited: true,                    ← 부하 O
  totalEncodeMsPerFrame: 28.5,         ← 3레이어 합산 부하
  activeLayers: 3,
  layers: [
    { fps: 12, encodeMsPerFrame: 14.2,
      qualityLimitationReason: "cpu",
      powerEfficientEncoder: false }   ← SW 인코딩 + CPU 제한
  ]
}

1레이어 전환 토글 A/B 비교

테스트 모드 디버그 패널(GuestDebugPanel)에 Camera Simulcast 1 Layer / 3 Layers 버튼을 추가했다. 클릭하면 카메라 producer를 닫고 새 encodings로 재생성한다.

노출 경로: use-mediasoup-produceruse-guest-page-sessionguest-layoutGuestDebugPanel. 테스트 모드(isTestMode)에서만 노출되어 운영 게스트에는 보이지 않는다.

검증 절차 (A/B)

  1. 3레이어 측정: [SIMULCAST-LOAD] Camera encoder stats에서 cpuLimited·totalEncodeMsPerFrame·레이어별 fps를 10~20초 안정화 후 기록
  2. 1 Layer 버튼 클릭 → producer 재생성
  3. 1레이어 측정: 같은 로그 재확인 후 비교
주의: 재생성 직후 첫 1~2개 로그는 delta 기준값 리셋으로 encodeMsPerFrame=null이거나 튄다 → 무시. 같은 단말·같은 조명/움직임 조건에서 비교해야 유효(움직임 많으면 인코딩 부하 ↑). activeLayers가 3→1로 바뀌었는지로 토글 반영 확인.
판정: 1레이어에서 cpuLimited:false로 풀리고 totalEncodeMsPerFrame이 크게 하락 → simulcast 3레이어가 부하 원인 확정. 여전히 cpuLimited:true면 → 인코딩 외 요인(디코딩·오디오·Realtime)이 주범.

DECODE_OVERLOAD · 업링크 stall 연관성 분석

코드 확인 결과 공통 근본 원인(단말 리소스 포화)을 공유하지만 코드상 직접 인과는 없는 독립 증상이다.

↔ DECODE_OVERLOAD : 강함 (CPU/코덱 경합)

↔ socket.io 업링크 stall : 약함/간접 (대역폭 경합)

교차 검증: LogRocket에서 타임스탬프 매칭 — [SIMULCAST-LOAD] Camera encoder statscpuLimited:true 시점이 Video waiting [DECODE_OVERLOAD] warn과 겹치면 CPU/코덱 경합 공통 원인 확정. 1레이어 토글로 DECODE_OVERLOAD 빈도·업링크 stall(GuestUplinkStall) 이벤트가 함께 줄어드는지 보면 두 연관성을 한 번에 확인.

변경 파일 (브랜치 test/simulcast-load)

파일변경
hooks/mediasoup/use-mediasoup-producer.ts인코딩 config 로그 + 레이어별 encoder stats 주기 로그 + simulcastLayerCount state + debugSetSimulcastLayers
entities/guest-page-session/model/use-guest-page-session.ts토글 함수·state 노출
widgets/guest/guest-layout/ui/guest-layout.tsx디버그 패널에 props 전달
widgets/guest/guest-layout/ui/guest-debug-panel.tsx1↔3 레이어 토글 버튼 UI

관련 문서