재생목록 요청은 성공했고 플레이어 오류도 0건이었습니다. 그런데 141.97초 목록에서 브라우저가 인식한 구간은 80.03초였습니다. 61.94초가 차이 났고, 60초로 탐색하면 약 87초로 이동했습니다. 원하는 장면을 골라 클립을 만드는 기능에서는 오류 수보다 이 잘못된 탐색이 먼저 해결할 문제였습니다.
저는 HTTP 상태와 오류 로그만 보던 확인을 선언 길이·브라우저 버퍼·실제 탐색 위치의 대조로 넓혔습니다. AI와 원인을 분석하며 재생목록 태그를 바꾸는 시도를 비교했지만, 파일 내부 시간이 겹치는 문제는 남았습니다. 여기서 원본은 보존하고 재생용 파일의 시간축을 별도로 구성하는 방향으로 바꿨습니다.
세 개의 시계가 같은 말을 하지 않았습니다
재생목록은 파일을 어떤 순서와 길이로 읽을지 알려 줍니다. 그러나 각 파일 안에도 샘플을 놓을 시각이 있습니다. fMP4의 tfdt는 디코딩 시작 시각을 담습니다. 당시 녹화 파일은 독립적으로 재생할 수 있도록 파일마다 상대 시간이 다시 시작했으므로, 목록의 순서대로 늘어놓는 것만으로 하나의 미디어 시간축이 되지 않았습니다.
| 확인한 대상 | 초기 관측 |
|---|---|
| 재생목록에 선언한 길이 | 141.97초 |
| 브라우저가 인식한 구간 | 80.03초 |
| 두 값의 차이 | 61.94초 |
| 60초 탐색의 실제 이동 | 약 87초 |
| 플레이어 오류 | 0건 |
목록과 브라우저의 차이는 141.97−80.03=61.94초, 목록 길이 대비 약 43.63%입니다. 초기 메모의 “42%” 대신 이 두 관측값으로 계산했으며, 측정 요약에도 절대 차이를 표시했습니다. 중요한 것은 비율만이 아닙니다. 60초 요청이 87초로 이동한다면 전체 길이를 표시하는 UI만 고쳐서는 원하는 장면을 선택할 수 없습니다.
태그를 바꾸는 시도만으로는 충분하지 않았습니다
처음에는 재생목록의 안내를 보완하는 접근을 비교했습니다. 절대 시각을 알려 주는 PROGRAM-DATE-TIME, 초기화 정보를 지정하는 EXT-X-MAP, 연속되지 않는 구간을 알리는 DISCONTINUITY입니다. 각각의 태그가 다루는 문제는 다릅니다. HLS 규격 RFC 8216도 이 역할을 별도로 정의합니다.
| 시도 | 보완하려던 것 | 남은 문제 |
|---|---|---|
| PROGRAM-DATE-TIME | 절대 시각과 미디어의 연결 | 파일 내부 상대 시간의 중첩 |
| EXT-X-MAP | 코덱·트랙 초기화 정보 | 조각 간 시간 위치 |
| DISCONTINUITY | 연속성 변화 표시 | 일부 경계의 빈 구간·멈춤 |
절대 시각을 써 넣었다고 파일의 내부 시간값이 자동으로 바뀌지는 않습니다. init을 제공해도 플레이어가 해석할 샘플의 시간 배치가 여전히 겹칠 수 있습니다. DISCONTINUITY는 일부 구간을 살렸지만, 이후에는 경계의 간극과 멈춤을 따로 추적해야 했습니다. “태그를 추가했으니 정상”이라는 결론을 내리기 어려웠습니다.
원본과 재생 산출물의 책임을 나눴습니다
이때 선택한 방향은 녹화 원본을 보존하고, S3·CDN에 전달할 재생용 파일에서 트랙과 시간축을 명시적으로 만드는 것이었습니다. 편집용 원본에는 여러 오디오 트랙이 필요하므로 재생 문제를 해결한다고 원본을 덮어쓰면 다른 기능의 재료를 잃습니다.
원인은 MediaMTX가 파일마다 상대 시간을 쓰는 것 자체의 결함이 아니었습니다. 독립적으로 읽는 녹화 파일과 이어 보는 방송은 필요한 시간 표현이 다릅니다. 공식 playback 경로는 그 사이에서 시간을 재배치합니다. PokeClip이 S3·CDN 직접 전달을 선택하면서 생략한 책임을 우리 재생 산출물에 가져와야 했습니다.
태그를 더 넣기 전에 시간값만 바꿔 보기
다음 질문은 파일을 변환했더니 된다는 결과에서 어떤 변경이 작용했는지를 구분하는 것이었습니다. 동일 녹화 파일 10개로 공통 init만 분리한 경우와 tfdt까지 바꾼 경우를 나눈 단일 변수 대조를 진행했습니다. 이후 10분·150조각·재접속 2회의 경계 검증으로 범위를 넓혔습니다. 초기 141.97초, 다음 39.87초, 후속 10분 입력은 서로 다른 데이터이므로 각 시험의 결과는 따로 읽어야 합니다.
처음의 “오류 0건”은 버리지 않고 성공 조건의 일부로 남겼습니다. 여기에 buffered가 이어지는지와 요청한 위치에서 재생하는지를 더했습니다. 원본 보존은 편집 기능의 재료를 지키고, 별도 시간축 변환은 그 원본을 되감기에서 사용할 책임을 맡습니다. 원하는 장면을 고르는 기능에 맞춰 검사 대상과 구현 경계를 함께 바꾼 결과입니다.
이 글은 PokeClip의 개발·검증 기록을 2026년 10월 15일 기준으로 정리한 CASE 22입니다. 전체 기술 기록에서 연결되는 결정을 함께 읽을 수 있습니다.