방송이 끊겼다가 돌아온 뒤 전체 재생 길이는 맞았지만, 경계에 약 0.2초의 빈 구간이 남았습니다. 오디오가 먼저 끝나므로 다음 조각을 앞으로 당기면 될 것 같았습니다. 그런데 시간값을 당겨도 불연속 태그가 있으면 버퍼는 여전히 세 개로 갈라졌습니다.
저는 다음 조각의 위치와 DISCONTINUITY 표시를 한 쌍으로 대조했습니다. 같은 회차·동일 init에서 이른 트랙 끝에 맞추고 표시를 생략한 경우 버퍼가 하나로 이어졌습니다. 후속 10분·150조각·재접속 2회 입력에서는 hls.js 탐색 12/12가 성공했습니다. 대신 영상 타임스탬프가 겹칠 수 있는 비용도 남았습니다.
실측·구현은 AI와 협업했습니다. 저는 비교할 경계와 적용 범위를 정하고, 코덱 설정이 같은 입력에 한정해 이 규칙을 채택했습니다. 2026년 9월 19일 최초 실험과 9월 23일 후속 검증입니다.
영상의 끝에 맞추면 오디오가 비었습니다
끊김 직전 마지막 조각의 오디오는 영상보다 0.19~0.22초 먼저 끝났습니다. 예를 들어 영상이 10.00초, 오디오가 9.80초에 끝나는데 다음 조각을 10.00초에 놓으면 오디오에는 0.20초가 빕니다. 이 숫자 예시는 동작 설명용이고, 실제 관측 범위는 앞의 0.19~0.22초입니다.
이른 트랙 끝에 붙이면 오디오의 빈틈을 줄일 수 있지만 영상은 앞 조각과 겹칠 수 있습니다. 어느 쪽이든 비용이 있습니다. 더구나 타임스탬프를 먼저 끝난 트랙에 맞췄어도 DISCONTINUITY를 유지하면 hls.js가 자체 계산으로 새 구간을 놓아 버퍼가 다시 갈라졌습니다.
| 변형 | 다음 조각 위치 | 불연속 표시 | 관측 버퍼 |
|---|---|---|---|
| A | 늦은 트랙 끝 | 있음 | 3개로 분리 |
| B | 이른 트랙 끝 | 있음 | 3개로 분리 |
| C | 이른 트랙 끝 | 생략 | 1개로 연결 |
A→B에서는 배치 위치만 바꿨는데도 버퍼 세 개가 그대로였습니다. B→C에서 표시를 생략하자 하나가 됐습니다. 파일에 쓴 시각을 플레이어가 그대로 쓰는지까지 봐야 한다는 뜻이었습니다. 시간값을 보정하고 태그는 관성적으로 유지하는 조합으로는 이 입력의 빈틈을 해결하지 못했습니다.
녹화기의 표식은 논리 회차와 같지 않았습니다
시간 보정에는 mtxi의 누적 시각과 회차 안 보정값을 사용합니다. 녹화기의 표식이 바뀌거나 큰 시간 구멍이 나타나면 다음 조각을 이어 붙일 위치를 다시 판단합니다. 표식이 바뀌어도 DTS는 계속 증가하는 드리프트 리셋이 있어, DTS가 뒤로 갔는지만으로 재접속을 분류하지 않았습니다.
동시에 녹화기 식별자가 바뀌었다고 곧바로 새 논리 방송으로 볼 수도 없습니다. 같은 방송 안에서 연결이 재수립될 수 있기 때문입니다. 이 구분은 방송 회차와 종료 목록 설계와 연결됩니다. 시간 보정은 동일 회차 안의 연속성을 다루고, 회차 전환은 별도의 종료·주소 규칙을 따릅니다.
150개 init이 같았던 입력에서 확인했습니다
실험 입력은 10분 방송, 150조각, 재접속 2회입니다. 150개 init 해시가 1종이었던 조건에서 비교했습니다. 후속 C′는 EXTINF를 원래 영상 길이로 유지했는데도 경계를 통과했습니다. 목록 길이까지 바꿔야만 성공한 것인지도 분리한 셈입니다.
| 후속 C′ 확인 항목 | 결과 |
|---|---|
| hls.js 1.7.3 오류 / stall | 0 / 0 |
| 탐색 | 12/12 성공 |
| 버퍼 | 단일 구간 |
| EXTINF | 원래 영상 길이 유지해도 경계 통과 |
| AVFoundation | 두 재접속 경계 통과 |
EXTINF를 되돌린 C′도 통과했으므로, 이 입력에서는 목록 길이를 함께 바꿔야만 경계를 넘는 것은 아니었습니다. 후속 검증 상세는 HTTP 성공 외에 버퍼·탐색·다른 플레이어의 경계 통과를 대조합니다. 범위는 VOD형 목록의 고정 입력입니다. 슬라이딩 DVR·다른 버전과 소스는 추가 검증 대상이며, 오디오 신호 점검도 사용자 청취 품질 전체를 대신하지는 않습니다.
버퍼를 잇는 대신 겹치는 영상 시각을 받아들였습니다
HLS 규격의 불연속 태그는 시간 순서 등이 바뀌는 경계를 다룹니다. 이른 트랙에 맞출 때 영상 타임스탬프가 최대 약 0.22초 겹칠 수 있는데도 동일 init에서 표시를 생략한 것은, 확인한 플레이어 동작을 근거로 택한 제한된 예외입니다. 규격을 무시해도 된다는 일반 규칙이 아닙니다.
인코더 설정이 바뀌어 init이 달라지면 같은 방식으로 묶지 않습니다. 생산 계층에는 init 해시가 달라질 때 그 조각을 실패로 두고 회차를 종료 방향으로 전이시키는 가드가 있습니다. 생산 PR #192는 속도뿐 아니라 이런 경계도 담고 있습니다.
보정값이 메모리에만 있는 단계의 재시작도 남은 과제입니다. 같은 회차에서 mtxi 리셋과 사이드카 재기동이 함께 일어나면 보정값을 잃어 도장이 뒤로 갈 수 있습니다. 재기동만으로 같은 역행이 생긴다고 단순화하지는 않지만, 재기동 전 업로드에 실패한 조각이 GAP으로 남는 문제는 별도로 존재합니다.
결국 약 0.2초의 오디오 빈틈을 줄이는 선택은 영상 시각의 일부 겹침을 받아들이는 선택이기도 했습니다. 그래서 동일 회차·동일 init을 적용 조건으로 묶고, init이 달라지는 입력에는 종료 가드를 뒀습니다. 고정 입력의 단일 버퍼·12회 탐색 성공과 아직 남은 재기동 복구를 구분해야, 이 예외를 새로운 입력에 무심코 넓히지 않을 수 있습니다.
이 글은 PokeClip의 개발·검증 기록을 2026년 10월 15일 기준으로 정리한 CASE 25입니다. 전체 기술 기록에서 연결되는 결정을 함께 읽을 수 있습니다.