웹캠 실제 스트림 테스트 — 상대방이 실제로 보는 것
웹캠 미리보기에 보이는 이미지는 getUserMedia()를 통해 전달된 로컬 캡처 뷰이지 원시 센서 출력이 아닙니다. 화상 통화 상대가 받는 이미지는 WebRTC에 의해 조용히 협상, 압축, 다운그레이드된 브라우저 인코딩 스트림입니다. 이 가이드는 WebRTC 코덱 협상의 작동 방식, RTCPeerConnection에서 getStats()를 사용하여 실제 스트림 매개변수를 측정하는 방법, 품질 손실의 일반적인 원인을 수정하는 방법을 설명합니다. 이 사이트의 웹캠 도구는 로컬 캡처 트랙과 브라우저 프레임 레이트만 확인하며, 아웃바운드 WebRTC 인코딩 스트림을 측정하지 않습니다.
화상 통화에 앉아 있는데 자기 창에 선명하고 잘 조명된 1080p 이미지가 보입니다니다. 당신은 또렷하고, 배경은 깨끗하고, 프레이밍도 좋습니다. 그런데 동료가 당신의 비디오가 계속 얼어붙고 흐릿다고 말하고, 그들이 화면을 공유할 때 당신은 10년 전 저가 웹캠이 만들었을 법한 블록적이고 뭉개진 그림을 봅니다. 같은 카메라. 같은 조명. 같은 컴퓨터. 다른 이미지.
대부분의 화상 통화 가이드가 건너뛰는 것이 있습니다. 그 격차는 보통 하드웨어 결함이나 센서 결함이 아닙니다. (물론 오작동하는 드라이버가 가끔 원인이 되기도 합니다.) 그것은 일반적으로 카메라가 생성하는 것과 브라우저가 실제로 보내는 것의 차이입니다. 미리보기는 WebRTC 인코딩 이전의 로컬 캡처 경로에서 공급됩니다. 상대방이 받는 것은 떠나기 전 밀리초 안에 WebRTC에 의해 협상, 재인코딩, 속도 제한, 다운그레이드된 압축 스트림입니다.
그 인코딩 계층은 사용자 인터페이스에서 보이지 않고 정상 작동 중에 조용합니다. 통화 창 어디에도 그것이 존재한다고 알려주지 않고, 결정을 보고하지 않으며, 미리보기에 반영하지 않습니다. 익숙한 장면: 사용자가 통화에서 흐릿한 이미지 때문에 카메라 드라이버를 시간 낭비하며 재설치하지만, chrome://webrtc-internals로 브라우저가 대역폭 추정에 따라 480p15로 협상하고 있었음을 발견합니다. 이 페이지는 카메라 센서와 통화 상대방의 화면 사이에서 무슨 일이 일어나는지, 브라우저가 왜 조용히 품질을 낮추는지, 그리고 가장 중요하게는 미리보기를 믿는 대신 기기를 떠나는 실제 스트림을 어떻게 측정하는지 설명합니다.

미리보기가 보여주지 않는 것
화상 통화는 전적으로 인식 밖에서 실행되는 파이프라인에 기반합니다. 당신이 보내는 각 프레임은 다음 단계를 통과합니다:
- 카메라 센서가 프레임을 캡처하고 브라우저는 getUserMedia()를 통해 요청된 해상도와 프레임 레이트로 전달합니다.
- 브라우저는
getUserMedia()API를 통해 프레임을 받아 WebRTC 엔진에 전달합니다. 로컬 미리보기는 이 단계에서 공급되므로 항상 완벽해 보입니다. - WebRTC 인코더가 협상된 코덱, 해상도, 프레임 레이트, 비트레이트로 프레임을 비트스트림으로 압축합니다.
- 인코딩된 프레임은 RTP 패킷으로 분할되어 네트워크를 통해 전송됩니다.
- 각 수신자는 패킷을 다시 디코딩하여 화면에 렌더링합니다.
미리보기는 2단계에서 파이프라인에 연결됩니다. WebRTC 인코딩 이전의 프레임을 표시합니다. 통화 상대가 보는 스트림은 3단계에서 나옵니다. 두 지점 사이에서 인코더가 세 가지 매개변수를 조용히 협상하며, 각각은 통화 중 알림 없이 변경될 수 있습니다:
- 해상도 — 인코딩된 프레임의 너비와 높이, 1920x1080에서 1280x720이나 640x480로 자체적으로 떨어질 수 있습니다.
- 프레임 레이트 — 인코딩을 통과하는 초당 프레임 수, 30에서 15 이하로 먼저 떨어지는 것이 일반적입니다.
- 비트레이트 — 인코더가 사용할 수 있는 초당 비트 수, 전체 압축 수준을 설정합니다.
이 세 가지 값이 상대방이 보는 모든 것을 결정합니다. 낮은 비트레이트로 압축된 1080p 이미지는 부드럽고 번집니다. 30fps 스트림이 갑자기 10fps로 실행되면 끊기고 부자연스럽게 보입니다. 미리보기가 이 값들을 보고하지 않는다는 것을 이해하면, 좋은 카메라로 끔찍한 통화의 미스터리가 해소됩니다.
SDP가 프레임 전송 전에 협상
협상은 첫 프레임이 전송되기 전에 시작됩니다. 통화에 참여하면 플랫폼과 브라우저가 Session Description Protocol(SDP) 오퍼와 앤서를 교환합니다. SDP는 각 측이 지원하는 코덱과 미디어 기능을 광고합니다. 실제 해상도와 프레임 레이트는 송수신 매개변수를 통해 추가 협상되며 대역폭 추정에 의해 제한됩니다.
코덱 선택은 시작일 뿐입니다. 통화가 시작되면 두 번째 메커니즘이接管합니다: 대역폭 추정. WebRTC는 양 방향의 네트워크 경로를 지속적으로 모니터링하고 혼잡 제어 알고리즘을 실행합니다:
- 패킷 손실, RTCP 피드백 메시지를 통해 수신자가 보고.
- 왕복 시간, 패킷 전송과 도착 확인 사이의 지연.
- 처리량, 데이터가 실제로 연결을 가로지르는 유효 속도.
알고리즘은 이 측정값을 네트워크가 현재 운반할 수 있는 대역폭을 추정하는 모델에 공급합니다. 그 추정값이 인코더에 전달되는 목표 비트레이트가 되고, 인코더는 출력을 맞추기 위해 적응합니다. 추정이 떨어지면 인코더는 1초도 안 되는 시간에 더 낮은 비트레이트로 재인코딩합니다.
임계값은 대략적이며 사용 중인 혼잡 제어 알고리즘에 따라 다릅니다. 지속적인 패킷 손실이 대략 5%를 초과하면 목표 비트레이트 감소를 트리거할 수 있습니다. 1080p 30fps 스트림은 깨끗하게 보이기 위해 약 4~6Mbps의 업로드 대역폭이 필요합니다. 추정기가 1Mbps만 사용 가능하다고 결론지으면, 스트림을 강제로 밀어넣지 않고 목표를 낮추고 인코더는 해상도를 480p로, 프레임 레이트를 15fps로 낮춥니다. 추정이 더 떨어지면 그림은 다시 저하되어 320x240 대화형 머리까지 내려갑니다. (Google: WebRTC Congestion Control Whitepaper, 2019; RFC 8888: Congestion Control Feedback for RTP).

스트림이 숨기는 세 가지 실패 패턴
미리보기는 스트림의 실제 상태를 세 가지 반복되는 실패 패턴 뒤에 숨깁니다. 증상으로 각각을 인식하는 법을 배우세요. 올바른 수정이 각 경우마다 다르기 때문입니다. 세 가지 모두 하나의 징후를 공유합니다: 미리보기는 내내 완벽하게 유지됩니다. 인코더 이전에 샘플링되기 때문입니다. 인코딩된 스트림만 손상을 보여줍니다.
비트레이트 트랩
증상: 미리보기는 완벽하고 컴퓨터의 CPU는 유휴 상태입니다. 상대방은 절대 선명해지지 않는 흐릿하고 저해상도 이미지를 봅니다. 로컬 녹화는 훌륭하지만 통화는 안 좋습니다. 진단: 브라우저가 네트워크가 전체 스트림을 운반할 수 없다고 추정하고 비트레이트를 제한하여 인코더가 해상도를 줄이도록 강제했습니다. 제약은 카메라가 아니라 업로드 대역폭이나 미디어 서버의 릴레이 용량입니다. 속도 테스트를 실행하고 측정된 업로드를 1080p30에 필요한 4~6Mbps와 비교하세요.
손실 임계값
증상: 통화의 정지 이미지는 괜찮아 보이지만, 움직임은 끊기고 로봇처럼 보입니다. 오디오는 부드럽게 유지되지만 비디오는 버벅거리고, 몇 초마다 짧은 얼어붙음이 발생한 후 더 낮은 프레임 레이트로 재개됩니다. 진단: 패킷 손실이 간헐적으로 5% 임계값을 넘어 혼잡 컨트롤러가 반복적으로 목표 비트레이트를 줄이고 인코더가 프레임을 드롭하고 있습니다. 프레임 레이트가 먼저 떨어지는 것이 가장 저렴한 레버이기 때문입니다. Wi-Fi 간섭, 불량 이더넷 케이블, 손실과 지연을 추가하는 VPN을 확인하세요.
키프레임 얼어붙음
증상: 참여 후 또는 화면 공유 후 처음 2~5초 동안 상대방이 얼어붙거나 심하게 번진 이미지를 봅니다. 그런 다음 그림이 초점을 맞추고 다음 큰 장면 변화까지 정상적으로 작동합니다.
진단: 비디오 코덱은 두 가지 프레임 유형을 전송합니다. 키프레임은 전체 그림을 인코딩하고 고정 간격으로 나타납니다. 델타 프레임은 이전 프레임 이후의 변경만 인코딩합니다. 델타 프레임의 패킷이 손실되면 수신자는 재전송을 요청하거나 새 키프레임을 요청하거나 오류를 숨기면서 대기합니다. 요청이 성공하면 복구가 빠르지만, 실패하면 다음 예정된 키프레임이 도착할 때까지 그림이 얼어붙어 있습니다.

getStats()로 실제 스트림 측정
추측을 멈추세요. 숫자는 보기 좋지 않지만 사실입니다. WebRTC API는 인코더가 무엇을 하고 있는지 정확히 보고하는 통계 인터페이스를 노출합니다. RTCPeerConnection 객체에서 getStats()를 호출한 후 반환된 보고서에서 kind가 video인 outbound-rtp 항목을 필터링하세요. 주요 값:
- framesPerSecond(media-source 항목) — 카메라가 인코더에 전달하는 프레임 레이트. 30fps 카메라에서 30 미만이면 캡처 경로 자체가 문제입니다 — 이는 USB 대역폭 경합 문제인 경우가 많으며, USB 대역폭 경합 가이드에서 진단 방법을 설명합니다.
- framesPerSecond(outbound-rtp 항목) — 인코더가 실제로 생성하는 프레임 레이트. 입력보다 낮으면 인코더가 프레임을 드롭하고 있는 것입니다.
- frameWidth와 frameHeight(outbound-rtp 항목) — 인코딩된 해상도. 통화 설정과 비교하세요. 차이는 조용한 다운그레이드입니다.
- bytesSent(outbound-rtp 항목) — 총 인코딩된 데이터. 1초 간격으로 두 번 샘플링하고 차이에 8을 곱하여 실제 비트레이트를 계산하세요.
- packetsSent와 packetsLost — outbound-rtp 항목의 packetsLost는 항상 채워지지 않습니다; 손실률은 수신자 관점을 보고하는 remote-inbound-rtp 항목에서 더 신뢰성 있게 읽을 수 있습니다.
- currentRoundTripTime(candidate-pair 항목) — 네트워크 지연. 높은 RTT와 손실이 결합하면 혼잡을 나타냅니다.
코드를 작성할 필요가 없습니다. Chrome과 Edge는 chrome://webrtc-internals에 내장 통계 뷰어를 제공합니다. 회의에 참여하기 전에 열고, 녹화하고, 비디오 송신자의 outbound-rtp 항목을 검사하세요. 이것이 실제 플랫폼 통화에서 다운그레이드를 현행범으로 잡는 가장 빠른 방법입니다.
Zoom, Meet, Teams: 세 가지 다른 카메라
같은 카메라, 같은 노트북, 같은 네트워크가 다른 애플리케이션에서 눈에 띄게 다른 결과를 낼 수 있습니다. 모든 플랫폼이 브라우저의 WebRTC 구현 위에 자체 인코딩 정책을 적용하기 때문입니다.
- Zoom은 일반적으로 안정성을 우선시합니다. 해상도를 제한하고 오디오와 화면 공유를 안정적으로 유지하기 위해 비디오 품질을 희생할 수 있습니다.
- Google Meet은 측정된 대역폭에 적응하는 경향이 있으며, 해상도를 일찍 떨어뜨리고 조건이 개선되면 빠르게 복구합니다.
- Microsoft Teams는 자체 인코딩 및 후처리 파이프라인을 적용합니다. 이미지가 추가로 압축될 수 있습니다.
- 브라우저 네이티브 WebRTC는 플랫폼 정책 없이 협상된 스트림을 전송합니다. 하드웨어와 네트워크가 일반 WebRTC에서 제공할 수 있는 것에 가장 가까운 진실입니다.
실용적 결론: Zoom 통화와 Meet 통화를 비교하는 것은 카메라 테스트가 아닙니다. 각 플랫폼의 인코딩 결정을 테스트하는 것입니다. 먼저 일반 WebRTC 페이지나 웹캠 테스트 도구로 원시 스트림을 측정하세요. 원시 스트림이 깨끗한데 한 플랫폼이 여전히 안 좋으면, 플랫폼의 정책이 제약이며 하드웨어 업그레이드로는 변경되지 않습니다.
깨끗한 스트림을 위한 7단계
이 단계들은 각각 별개의 원인을 분리합니다. 스트림이 올바르게 보일 때 멈출 수 있지만, 각 변경 전후에 측정하여 수정이 실제로 숫자를 옮겼는지 확인하세요.
- 먼저 측정. chrome://webrtc-internals를 열거나 getStats()를 사용하여 해상도, 프레임 레이트, 비트레이트를 기록하세요. 원시 스트림이 이미 다운그레이드되어 있으면 카메라와 연결이 문제입니다. 깨끗하면 플랫폼이 문제입니다.
- 대역폭 확인. 화상 통화는 720p에 최소 1Mbps 업로드, 1080p에 약 4Mbps가 필요합니다. 호출하는 컴퓨터에서 테스트하세요. 가능하면 유선 연결로 전환하세요. Wi-Fi 손실은 보이지 않는 다운그레이드의 가장 일반적인 원인입니다.
- 조명 수정. 잘 조명된 피사체는 어두운 피사체보다 훨씬 더 잘 압축됩니다. 창을 향하거나 부드러운 광원을 사용하세요. 비용이 들지 않으며 어떤 설정보다 큰 개선을 자주 만듭니다.
- 비디오 노이즈 감소 비활성화. 환경이 이미 조용하고 잘 조명된 경우. 일부 플랫폼은 저조도 장면에서 공격적인 디노이징을 적용하여 미세 디테일을 부드럽게 할 수 있습니다.
- 가상 배경 비활성화. 배경 분할은 유효 비트레이트에 오버헤드를 추가하고 인코더의 GPU 사이클을 소비합니다. 일관된 조명의 깨끗한 실제 배경이 가상 배경보다 낫습니다.
- 코덱 확인. CPU가 감당할 수 있으면 VP9이 비트당 최상의 품질을 제공합니다. 프레임 드롭이나 CPU 스파이크가 보이면 H.264가 더 빠르게 인코딩됩니다.
- 다른 플랫폼 테스트. 한 서비스에서는 품질이 좋고 다른 서비스에서는 안 좋으면, 플랫폼의 인코딩 정책이 제약입니다. 하드웨어의 잘못이 아닙니다.
결론
미리보기는 카메라의 로컬 자기 이미지입니다. 스트림은 세상이 실제로 보는 것입니다. 협상, 압축, 네트워크 상태와 플랫폼 정책에 의해 형성됩니다. 같은 피사체의 두 가지 다른 비디오이며, 그중 하나만 당신이 어떻게 보이는지에 중요합니다.
chrome://webrtc-internals를 여세요. 다음 통화에 참여하세요. outbound-rtp 항목을 관찰하세요. frameWidth나 framesPerSecond가 카메라 설정보다 낮으면 다운그레이드가 발생하고 있는 것입니다. 원인은 일반적으로 대역폭 관련이지만, CPU 부하, 인코더 선택, 플랫폼 정책도 저하에 기여할 수 있습니다.