마지막 업데이트 2026-07-29
DECODE_OVERLOAD 발생 감소 — 인코딩 파라미터 및 lowPerf 기준 개선의 핵심을 수사반장식으로 먼저 안내합니다. 기술적 결론과 원문 근거는 아래 본문에 보존되어 있습니다.
3개 세션(아동303 25회기, 아동049 24회기, 아동074 2회기)에서 full:video 스텝 영상 재생 중 DECODE_OVERLOAD가 반복 발생하여 자동전환 실패 및 호스트 수동 개입이 7회 이상 확인됨.
Watchdog 설계 한계(별도 문서)와 함께, DECODE_OVERLOAD 자체를 줄이는 방향을 분석함.
줄이려면 먼저 무엇이 무거운지 알아야 한다. full:video 스텝에서 게스트 브라우저가 실제로 지고 있는 부하부터 목록화했다.
useMediasoupProducer만 사용하며 호스트 스트림을 consume하지 않음.
게스트 화면에는 자신의 웹캠(셀프뷰)이 렌더링됨.
오디오 파이프라인(Opus) pause 효과는 미미함. 근본 원인은 영상 디코딩 부하이므로 서버 인코딩 파라미터와 lowPerf 판정 기준이 핵심 개선 대상.
주 부하가 영상 디코딩으로 좁혀지자 질문은 둘로 나뉘었다 — 누가 무거운 영상을 받고 있는가(lowPerf 판정), 그리고 영상 자체가 왜 이렇게 무거운가(인코딩 파라미터). 3개 세션의 실제 데이터로 첫 번째 질문부터 확인했다.
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) | 반복 발생 (여전히) |
// apps/web/lib/utils.ts — 데스크탑/노트북 기준 완화 return hardwareConcurrency <= 24 || (memoryInfo > 0 && memoryInfo <= 48);
MediaCapabilities.decodingInfo() 결과를 1차 판단 기준으로 삼는 방안(하단 참고)이 더 정밀함.
그런데 판정 기준 완화만으로는 설명되지 않는 케이스가 있었다 — 아동074는 이미 lowPerf 판정을 받아 480p를 수신하고도 DECODE_OVERLOAD가 반복됐다. 480p 자체가 무겁다는 뜻이다.
# 현재 scale = 'scale=854:480:flags=lanczos,fps=30' maxrate = '1200k' bufsize = '2400k' crf = 22
활동 영상은 캐릭터 애니메이션 스타일 콘텐츠로 실사 영상 대비 정보량이 적음. 1200kbps는 이 콘텐츠 유형에 과도하며, 800kbps 이하로도 충분한 화질 유지 가능. fps=30 → 24 전환 시 초당 디코딩 프레임 20% 감소.
# 개선안 scale = 'scale=854:480:flags=lanczos,fps=3024' maxrate = '1200k800k' bufsize = '2400k1600k' crf = 22 # 동일 유지
| 항목 | 변경 전 | 변경 후 | 디코딩 효과 |
|---|---|---|---|
| fps | 30 | 24 | 초당 프레임 20% 감소 |
| maxrate | 1200kbps | 800kbps | 비트 처리량 33% 감소 |
| bufsize | 2400k | 1600k | 버퍼 소비 감소 |
| profile/codec | baseline, cabac=0, ref=1 | 동일 | 유지 |
두 처방은 모두 스펙 숫자(코어 수·메모리) 기반이라 거칠다. 6코어/8GB이지만 GPU 가속이 없는 기기처럼 스펙만으로 포착되지 않는 사례를 위해, 이미 존재하는 실측 API를 1차 기준으로 끌어올리는 방안을 함께 검토했다.
이미 _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 발생 시 자동전환 보장 (별도 문서) |