Bitrate와 화질 — 같은 해상도인데 왜 결과가 다른가
Bitrate는 해상도·frame rate·codec·장면 복잡도와 함께 압축 화질을 좌우합니다. 이 글은 송출 설정, 네트워크 적응, Cloud Recording 출력 설정을 구분하고 `ffprobe`로 실제 결과를 측정하는 절차를 설명합니다. 출력 bitrate를 높여도 원본에서 이미 잃은 디테일은 복원되지 않으므로 실제 콘텐츠로 품질을 비교해야 합니다.
목차(26개 항목)
- Bitrate란 — 초당 데이터 예산
Resolution × FPS × Bitrate — 세 변수의 삼각관계
Cloud Recording에서 Bitrate가 결정되는 흐름
"같은 해상도인데 왜 뭉개지나" — 실제 사례
CBR vs VBR — Bitrate 할당 개념
- 호스트 Bitrate > 녹화 Bitrate — 무슨 일이 일어나는가
- 핵심 요약
- 시리즈 네비게이션
- 관련 글
- 참고 자료
같은 720×1280인데 왜 한쪽은 선명하고 한쪽은 뭉개져 보이는가? 해상도가 같아도 bitrate와 입력·인코딩 조건이 다르면 화질이 달라집니다. 해상도가 캔버스 크기라면 bitrate는 encoder가 초당 사용할 수 있는 데이터 예산입니다.
Cloud Recording에서 해상도는 설정값과 같지만 디테일이 무너지는 경우가 있습니다. 이때 bitrate는 우선 확인할 항목이지만, 입력 화질, 프레임률, codec, 재인코딩과 네트워크 적응도 함께 봐야 합니다.
Bitrate란 — 초당 데이터 예산
Bitrate는 1초 동안 영상을 표현하는 데 사용할 수 있는 데이터량입니다.
정지 이미지의 압축 품질을 떠올리면 직관을 잡는 데 도움이 되지만, 영상 codec은 시간축의 프레임 간 예측까지 사용합니다. 따라서 특정 bitrate를 JPEG 품질 값과 일대일로 대응시킬 수는 없습니다.
Resolution × FPS × Bitrate — 세 변수의 삼각관계
화질을 결정하는 세 변수는 서로 얽혀 있습니다. 하나를 올리면 다른 것도 따라 올려야 합니다.
계산 직관
세 변수 중 하나만 올리고 나머지를 고정하면 이런 일이 벌어집니다.
| 변경 | 결과 |
|---|---|
| 해상도↑ bitrate 고정 | 큰 캔버스에 적은 물감 → 뭉개짐 |
| FPS↑ bitrate 고정 | 프레임마다 예산 줄어듦 → 각 프레임 품질↓ |
| Bitrate↑ 해상도·FPS 고정 | 일정 수준까지 선명해지다가 수확 체감 |
권장 bitrate를 정하는 방법
Agora SDK는 해상도와 FPS 조합별 standard bitrate를 제공하며, SDK와 플랫폼에 따라 사용할 수 있는 preset과 범위가 다릅니다. 오래된 FAQ의 base/live 표를 고정값으로 복사하지 말고 현재 사용 중인 SDK의 video encoding 문서를 기준으로 설정합니다.
같은 해상도에서도 FPS가 높거나 움직임이 복잡하면 일반적으로 더 많은 bitrate가 필요합니다. 최종 값은 대표 장면에서 실제 송출 통계와 녹화 결과를 측정해 정합니다.
Cloud Recording에서 Bitrate가 결정되는 흐름
녹화 화질은 단일 설정으로 결정되지 않습니다. 호스트 SDK에서 출발한 영상이 최종 녹화 파일이 되기까지 여러 단계를 거칩니다.
각 단계에서 화질이 깎이는 방식
① 호스트 SDK 설정 — 송출 목표값의 출발점입니다. 실제 입력 품질과 network adaptation 때문에 설정값이 결과의 품질을 보장하지는 않습니다.
② 네트워크 적응 — SDK는 네트워크 상태에 맞춰 실제 송출 품질을 조정할 수 있습니다. 어떤 속성이 어느 순서로 바뀌는지는 SDK와 degradation preference 설정에 따라 다릅니다. 설정값과 실제 송출값은 다를 수 있습니다.
③ Cloud Recording 수신 — videoStreamType: 0은 high-quality stream, 1은 low-quality stream을 구독하도록 지정합니다. channelType은 앱의 channel profile과 맞춰야 하지만, 이 값만으로 특정 화질 저하를 진단할 수는 없습니다.
④ Composite 모드 재인코딩 — transcodingConfig의 출력 해상도, FPS와 bitrate가 적용됩니다. 입력보다 낮은 bitrate로 다시 인코딩하면 압축 손실이 커질 수 있습니다. 결과는 장면과 encoder 동작을 함께 측정해야 합니다.
"같은 해상도인데 왜 뭉개지나" — 실제 사례
아래는 진단 방법을 보여주기 위한 예시 설정입니다.
상황
ffprobe로 확인
해상도는 720×1280으로 정상. 그런데 bit_rate=N/A입니다.
HLS에서 bit_rate가 N/A인 이유
먼저 짚어야 할 구분이 있습니다. HLS(RFC 8216)에는 두 종류의 플레이리스트가 있습니다.
즉 M3U8에 bitrate 정보가 전혀 없는 것은 아닙니다. Master 플레이리스트의 EXT-X-STREAM-INF는 BANDWIDTH(bits/sec) 속성을 필수로 가집니다(RFC 8216 §4.3.4.2). 다만 이 값은 여러 화질 variant를 묶을 때 클라이언트가 대역폭에 맞는 variant를 고르라고 제공하는 메타데이터일 뿐, 개별 media 플레이리스트 자체에는 전체 bitrate 필드가 없습니다.
Cloud Recording의 녹화 M3U8은 media playlist이므로 EXT-X-STREAM-INF:BANDWIDTH가 없습니다. 이 입력에서 ffprobe가 stream bitrate를 추정하지 못하면 N/A를 표시할 수 있습니다. MP4도 bitrate metadata가 항상 존재하는 것은 아니며, 도구가 파일 크기와 재생 시간으로 평균 bitrate를 계산해 표시할 수 있습니다.
전체 bitrate를 알고 싶다면 개별 TS 세그먼트를 분석해야 합니다.
화질 저하의 원인 분석
해상도가 정상이라면 문제는 이 세 가지 조합입니다.
CBR vs VBR — Bitrate 할당 개념
CBR과 VBR은 자주 쓰는 두 개념입니다. 실제 encoder에는 capped VBR, average bitrate, CRF 등 더 다양한 rate-control 방식이 있습니다.
CBR (Constant Bitrate) — 고정 비트레이트
CBR은 설정한 시간 구간과 buffer 제약 안에서 bitrate를 일정하게 유지하려는 방식입니다. 개별 frame이나 순간 bitrate까지 정확히 같다는 뜻은 아닙니다. 대역폭 예측이 중요한 실시간 전송에 사용됩니다.
VBR (Variable Bitrate) — 가변 비트레이트
VBR은 장면 복잡도에 따라 bitrate를 다르게 할당합니다. 목표 평균값이나 상한을 함께 둘 수 있으며 VOD encoding에 널리 사용됩니다.
Cloud Recording의 bitrate 설정
transcodingConfig.bitrate는 Composite 출력 encoder에 전달되는 bitrate 설정입니다. 공개 문서만으로 내부 rate-control 구현을 CBR 또는 VBR로 단정할 수 없으므로, 실제 결과의 평균·peak bitrate와 품질을 측정해야 합니다.
호스트 Bitrate > 녹화 Bitrate — 무슨 일이 일어나는가
흔한 질문입니다. "호스트가 1710으로 보내는데 녹화를 2500으로 설정하면 더 좋아지나요?"
녹화 bitrate를 호스트보다 높게 설정해도 원본에 없는 디테일을 복원할 수는 없습니다. 다만 재인코딩 과정에서 추가 손실을 줄이는 데 필요한 bitrate는 입력 bitrate와 같지 않을 수 있습니다.
출력 bitrate가 너무 낮으면 압축 아티팩트가 늘어날 가능성이 큽니다. 적정값은 고정 비율로 정하지 말고 입력 통계, 출력 해상도·FPS, 장면 복잡도와 목표 품질로 검증합니다.
실전: 화질이 나쁠 때 디버깅 체크리스트
녹화 화질 문의가 왔을 때 순서대로 확인합니다.
Step 1: 실제 해상도 확인
설정한 해상도와 다르면 실제 송출 통계, subscription stream type, transcoding canvas와 layout 설정을 차례로 확인합니다.
Step 2: channelType 일치 확인
Step 3: FPS 일치 확인
Step 4: Bitrate 적정성 확인
Step 5: 방향(Orientation) 일치 확인
핵심 요약
- Bitrate는 초당 데이터 예산입니다. 해상도·FPS·장면 복잡도·codec과 함께 판단합니다.
- SDK preset은 현재 버전 문서를 확인합니다. 오래된
base/live표를 공통 기준으로 쓰지 않습니다. - Composite 모드는 출력 설정으로 재인코딩하므로 입력보다 낮은 bitrate에서 손실이 커질 수 있습니다.
- 높은 출력 bitrate는 입력 디테일을 복원하지 못하지만, 재인코딩 손실을 줄일 여지는 측정해야 합니다.
- media playlist에는 variant
BANDWIDTH가 없습니다. ffprobe가N/A를 표시하면 segment 크기와 실제 duration으로 평균값을 계산합니다. - 화질 진단은 실제 송출 통계부터 시작해 subscription, 출력 해상도·FPS·bitrate, layout과 codec을 확인합니다.
시리즈 네비게이션
실시간 통화, 어떻게 녹화하는가 시리즈
관련 글
- #14 Agora 녹화 모드 비교 — Individual, Composite, Web page — Composite 모드 재인코딩이 어디서 일어나는지, 본문의 generation loss 단계를 파이프라인 관점에서 보완
- #15 M3U8과 TS 구조 — HLS 녹화 파일 읽기 — master/media 플레이리스트 구분과, 단일 media 플레이리스트라 ffprobe가 N/A를 내는 이유의 근원
- #28 H.264 Profile·인코더·비트레이트 — bitrate가 코덱/프로파일 레벨에서 어떻게 소비되는지, 본문의 "데이터 예산"을 인코더 내부로 확장
- #43 Agora 자체 코덱 vs Web SDK, SD-RTN, FEC — 본문 ②단계 "네트워크 적응"이 SD-RTN과 FEC 위에서 어떻게 동작하는지
- #38 ABR Ladder Layer B 정렬 — 키프레임 동기화 — VBR/CBR 선택이 ABR 사다리의 각 레이어 bitrate 설계와 어떻게 연결되는지
참고 자료
- Agora — Configure video encoding — 현재 SDK의 dimensions, frame rate와 bitrate 설정 지침.
- Agora Cloud Recording — Composite mode —
transcodingConfig와 Composite 녹화 요청 구조. - Agora Cloud Recording REST API Reference —
videoStreamType,channelType등 현재 REST 요청 필드. - FFprobe Documentation — FFmpeg —
bit_rate가 컨테이너 메타데이터에서 어떻게 보고되는지(HLS에서 N/A가 나는 동작) - HTTP Live Streaming (RFC 8216) — M3U8 플레이리스트 구조. master 플레이리스트의
EXT-X-STREAM-INF는BANDWIDTH(§4.3.4.2)를 필수로 가지나, media 플레이리스트는 세그먼트 목차일 뿐 전체 bitrate 필드가 없음 - ISO/IEC 14496-12 — ISO base media file format — MP4 계열 container 구조의 표준.