개발 서버에 방송을 연결했는데 플레이어는 검은 화면만 보여 줬습니다. 송출 인증은 성공했고 일부 요청은 200이었습니다. 서버 오류 하나를 없애도 화면은 그대로였습니다. 그 오류가 원인이 아니었던 것인지, 다른 문제가 함께 있었던 것인지 다음 증거로 구분해야 했습니다.
2026년 8월 18일, 저는 서버의 영상 해석 → 재생목록과 객체 → 브라우저 초기화 순서로 조사를 나누었습니다. 수정과 실측은 AI 협업으로 진행했고, 한 단계가 통과해도 실제 재생까지 조사하도록 범위를 정했습니다. MediaMTX 1.19.3과 당시 OBS·브라우저 조건에서 세 문제가 이어져 드러난 개발 서버 진단입니다.
인코딩 설정을 바꾸자 서버 오류만 사라졌습니다
서버 로그에는 too many reordered frames (11)이 반복됐습니다. 당시 OBS의 B-frame 인코딩과 LL-HLS 분할에서 MediaMTX HLS muxer가 DTS를 계산하지 못하는 경로였습니다. OBS를 baseline과 키프레임 2초 설정으로 바꾼 뒤 반복 오류가 사라졌습니다.
그런데 화면은 돌아오지 않았습니다. 반복 오류가 없어졌다는 결과는 해당 muxer 실패를 없앴다는 뜻이지, 플레이어가 읽을 파일까지 정상이라는 뜻은 아니었습니다. 다음에는 플레이어에 전달된 재생목록을 확인했습니다.
| 조사 단계 | 당시 증거 | 조치 뒤 확인할 것 |
|---|---|---|
| 영상 해석 | 프레임 재정렬 오류 반복 | 반복 오류 소멸 |
| 목록·객체 | gap.mp4 7개, 401 |
목록의 GAP 0개 |
| 브라우저 초기화 | variant·조각 200인데 정지 | JS 로드·옵션·실제 재생 진행 |
새 조각이 정상이어도 목록에는 실패한 구간이 남았습니다
재접속 중 생긴 gap.mp4 7개가 긴 재생 창의 앞쪽에 남아 401을 반환하고 있었습니다. 새 조각을 정상적으로 만들기 시작해도, 플레이어가 목록에 남아 있는 과거 구간을 읽으면 다시 실패했습니다. 생산자가 복구된 시점과 소비자가 정상 구간만 받는 시점이 달랐던 것입니다.
당시에는 hlsSegmentCount를 900 → 30으로 잠시 줄여 오래된 GAP을 창 밖으로 내보냈습니다. GAP이 0개가 된 것을 확인한 뒤 다시 900으로 복원했습니다. 영구적으로 재생 창을 줄인 것이 아니라 긴 개발용 창에 남은 실패 구간을 제거한 복구 조치였습니다.
설정의 의미는 MediaMTX 설정 문서에서 확인할 수 있습니다. 다만 이 조치는 당시 1.19.3과 관측된 GAP에 대한 대응이며 모든 버전이나 서비스의 기본 설정으로 권하는 값은 아닙니다.
미디어가 200이어도 플레이어 초기화는 실패할 수 있었습니다
GAP을 제거한 뒤에는 302 리다이렉트 이후 variant 목록과 세그먼트가 200을 반환하는 것까지 확인했습니다. 그래도 화면은 멈춰 있었습니다. 브라우저 콘솔에서 hls.js 파일 로드 실패와 생성자 옵션 오류가 드러났습니다. 미디어를 요청할 수 있어도 플레이어를 만드는 JavaScript가 실패하면 재생을 시작할 수 없었습니다.
라이브러리를 같은 오리진에서 제공하도록 바꾸고, liveMaxLatencyDurationCount와 짝이 되는 liveSyncDurationCount: 3을 추가했습니다. 이는 서버 조각 길이가 아니라 플레이어의 라이브 동기화 설정입니다. 옵션 관계는 hls.js API 문서와 함께 확인했습니다.
앞의 수정이 소용없었던 것은 아닙니다. 영상 해석 오류를 없애니 오래된 GAP을 조사할 수 있었고, 목록·객체가 정상임을 확인한 뒤에는 플레이어 초기화로 범위를 좁혔습니다. 같은 검은 화면 뒤에 서로 다른 단계의 실패가 겹쳐 있었습니다.
재생과 되감기를 확인한 뒤 서버 변경도 남겼습니다
조치 뒤 브라우저에서 영상 재생과 되감기 조작을 확인했고, 조각 길이는 4.00000초로 관측했습니다. 접속 성공, muxer 동작, 목록·객체 응답, JS 초기화, 실제 재생을 각각 확인한 뒤에야 초기 증상이 해결됐다고 판단했습니다.
서버에서 고친 플레이어·프록시·마운트 설정과 저장소의 차이도 남겼습니다. 서버에서만 바뀐 설정이 다음 배포에 빠지면 같은 증상이 돌아올 수 있으므로, 재현 가능한 변경으로 옮기는 일도 후속 확인 대상이었습니다.
이 기록은 설정을 하나씩 독립 A/B 실험한 결과가 아니라 당시 오류와 조치의 순서를 대조한 진단입니다. 모든 MediaMTX에서 B-frame을 금지해야 한다는 결론이나, 이후 fMP4 시간축 문제까지 해결했다는 결과는 아닙니다. 검증 범위는 해당 개발 서버의 재생·되감기 복구입니다.
증상이 계속 남아 있을 때 이미 고친 부분을 무작정 다시 바꾸기보다, 통과한 단계와 아직 확인하지 못한 단계를 구분하는 편이 다음 조사를 좁혀 줬습니다. HTTP 200을 종착점으로 삼지 않고 실제 사용자가 재생을 보는 지점까지 확인한 것이 세 원인을 찾는 데 필요했습니다.