DECODE_OVERLOAD 발생 감소 ANALYSIS 개선 방안

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

연관 이슈: VideoEndWatchdog DECODE_OVERLOAD 반복 stall 미발화 관련 파일: apps/web/lib/utils.ts, Lambda 인코딩 함수 작성: 2026-06-17

배경

3개 세션(아동303 25회기, 아동049 24회기, 아동074 2회기)에서 full:video 스텝 영상 재생 중 DECODE_OVERLOAD가 반복 발생하여 자동전환 실패 및 호스트 수동 개입이 7회 이상 확인됨. Watchdog 설계 한계(별도 문서)와 함께, DECODE_OVERLOAD 자체를 줄이는 방향을 분석함.

full:video 스텝 게스트 브라우저 실제 부하

확인된 사항: 게스트는 useMediasoupProducer만 사용하며 호스트 스트림을 consume하지 않음. 게스트 화면에는 자신의 웹캠(셀프뷰)이 렌더링됨.
활동 영상 MP4 디코딩 ← 주 부하 H.264 720p/480p 게스트 카메라 H.264 인코딩 ← 중간 mediasoup으로 호스트에 송신 (유지 필요) 게스트 카메라 셀프뷰 렌더링 ← 낮음 srcObject 직접 표시, 추가 디코딩 없음 OpenAI Realtime Opus ← 낮음 응답 차단 상태, 파이프라인 유지 게스트 마이크 인코딩 ← 낮음 음소거 상태

오디오 파이프라인(Opus) pause 효과는 미미함. 근본 원인은 영상 디코딩 부하이므로 서버 인코딩 파라미터와 lowPerf 판정 기준이 핵심 개선 대상.

문제점 1 — lowPerf 기준 미달 기기가 720p 수신 BUG

현재 lowPerf 판정 기준 (apps/web/lib/utils.ts)

// 데스크탑/노트북
return hardwareConcurrency <= 2 || (memoryInfo > 0 && memoryInfo <= 4);
세션디바이스lowPerf 판정제공 해상도DECODE_OVERLOAD
아동303 25회기 6코어 / 8GB ❌ 정상 기기 판정 720p (maxrate 1800k) droppedFrames 31%
아동049 24회기 6코어 / 8GB ❌ 정상 기기 판정 720p (maxrate 1800k) 반복 발생
아동074 2회기 8코어 / 4GB ✅ lowPerf 판정 (≤4GB) 480p (maxrate 1200k) 반복 발생 (여전히)
아동303·아동049 케이스의 근본 원인: 6코어/8GB는 현재 기준을 통과하므로 720p 1800kbps를 수신. WebRTC 인코딩/전송 + AI 오디오 파이프라인과 동시에 720p를 디코딩하면 중간 사양 기기에서도 과부하가 발생할 수 있음.

개선: lowPerf 기준 완화

// apps/web/lib/utils.ts — 데스크탑/노트북 기준 완화
return hardwareConcurrency <= 24 || (memoryInfo > 0 && memoryInfo <= 48);
효과: 6코어/8GB 기기도 480p를 수신하게 됨. 수업 중 동시 미디어 부하를 감안한 보수적 기준.
부작용: 고성능 기기(예: M1 MacBook)도 480p를 받을 수 있음. MediaCapabilities.decodingInfo() 결과를 1차 판단 기준으로 삼는 방안(하단 참고)이 더 정밀함.

문제점 2 — 480p maxrate 1200k가 여전히 무거움 CAUSE

현재 480p 인코딩 파라미터 (Lambda)

# 현재
scale = 'scale=854:480:flags=lanczos,fps=30'
maxrate = '1200k'
bufsize = '2400k'
crf = 22

활동 영상은 캐릭터 애니메이션 스타일 콘텐츠로 실사 영상 대비 정보량이 적음. 1200kbps는 이 콘텐츠 유형에 과도하며, 800kbps 이하로도 충분한 화질 유지 가능. fps=30 → 24 전환 시 초당 디코딩 프레임 20% 감소.

개선: 480p 비트레이트 인하

# 개선안
scale = 'scale=854:480:flags=lanczos,fps=3024'
maxrate = '1200k800k'
bufsize = '2400k1600k'
crf = 22  # 동일 유지
항목변경 전변경 후디코딩 효과
fps3024초당 프레임 20% 감소
maxrate1200kbps800kbps비트 처리량 33% 감소
bufsize2400k1600k버퍼 소비 감소
profile/codecbaseline, cabac=0, ref=1동일유지
효과: 아동074 케이스처럼 480p를 받고도 DECODE_OVERLOAD가 발생하는 경우 감소 기대. 활동 영상 콘텐츠 특성상 24fps/800k에서 체감 화질 저하 없음.
필요 작업: Lambda 코드 수정 후 기존 업로드된 영상 전체 재인코딩 배치 실행 필요. 신규 업로드 영상부터는 자동 적용됨.

추가 개선 — MediaCapabilities 기반 정밀 판정

이미 _checkDesktopDecodingCapability() 함수가 존재하며 H.264 720p 30fps 1Mbps 기준으로 smooth && powerEfficient 여부를 확인함. 현재는 보조 수단으로만 사용 중.

// apps/web/lib/utils.ts — _checkDesktopDecodingCapability
const result = await navigator.mediaCapabilities.decodingInfo({
  type: "file",
  video: {
    contentType: "video/mp4; codecs=avc1.42E01E",
    width: 1280, height: 720,
    bitrate: 1_000_000, framerate: 30,
  },
});
// smooth=false OR powerEfficient=false → lowPerf 판정
제안: 하드웨어 스펙 기준(코어 수, 메모리)보다 MediaCapabilities 실측 결과를 우선 적용하면 기기 스펙만으로는 포착 못 하는 사례(6코어/8GB이지만 GPU 가속 미지원 등)를 커버 가능.

단, MediaCapabilities는 비동기 API이므로 앱 초기화 시 한 번 평가 후 캐싱하는 현재 방식 유지.

적용 우선순위

우선순위작업효과구현 비용비고
1 480p fps 30→24, maxrate 1200k→800k 높음 낮음 Lambda 수정 + 재인코딩 배치
2 lowPerf 기준 완화 (≤4코어 or ≤8GB) 높음 낮음 lib/utils.ts 1줄 수정
3 MediaCapabilities 판정 우선 적용 중간 중간 이미 함수 존재, 로직 연결 필요
4 VideoEndWatchdog wall clock drift 감지 중간 낮음 DECODE_OVERLOAD 발생 시 자동전환 보장 (별도 문서)
1+2를 동시에 적용하는 것이 가장 빠른 개선. 1은 서버 작업, 2는 프론트 작업으로 병행 가능. 4는 DECODE_OVERLOAD를 예방하지는 않지만 발생 시 자동전환을 보장하는 안전망이므로 함께 진행 권장.

관련 문서