Media Source Extensions (MSE)를 사용하는 경우 결국 처리해야 하는 한 가지 문제가 오버플로 버퍼입니다. 이 경우 QuotaExceededError
가 발생합니다. 이 도움말에서는 이 문제를 해결하는 몇 가지 방법을 설명합니다.
QuotaExceededError란 무엇인가요?
기본적으로 QuotaExceededError
는 SourceBuffer
객체에 너무 많은 데이터를 추가하려고 하면 발생합니다. 상위 MediaSource
요소에 SourceBuffer
객체를 더 추가해도 이 오류가 발생할 수 있습니다. 이러한 내용은 이 도움말에서 다루지 않습니다. SourceBuffer
에 데이터가 너무 많은 경우 SourceBuffer.appendBuffer()
를 호출하면 Chrome 콘솔 창에 다음 메시지가 트리거됩니다.
이와 관련해 몇 가지 유의해야 할 사항이 있습니다. 먼저 QuotaExceededError
이름이 메시지 어디에도 표시되지 않습니다. 이를 확인하려면 오류를 포착할 수 있는 위치에 브레이크포인트를 설정하고 보기 또는 범위 창에서 이를 검사합니다. 아래에서 확인해 보세요.
둘째, SourceBuffer
가 처리할 수 있는 데이터의 양을 확인할 확실한 방법이 없습니다.
다른 브라우저의 동작
이 문서를 작성하는 시점에는 Safari가 많은 빌드에서 QuotaExceededError
을 발생시키지
않습니다. 대신 2단계 알고리즘을 사용하여 프레임을 삭제하고 appendBuffer()
를 처리할 공간이 충분하면 중지합니다. 먼저 현재 시간으로부터 0~30초 사이의 프레임을 30초 단위로 해제합니다. 그런 다음 재생 시간에서 currentTime
후 30초까지 30초 단위로 프레임을 해제합니다. 자세한 내용은 2014년 Webkit 변경사항을 참고하세요.
다행히 Chrome과 함께 Edge와 Firefox에서도 이 오류가 발생합니다. 다른 브라우저를 사용 중이라면 직접 테스트해야 합니다. 실제 미디어 플레이어를 위해 빌드하지는 않겠지만, 프랑소와 보포르의 소스 버퍼 한도 테스트를 사용하면 적어도 동작을 관찰할 수 있습니다.
데이터를 얼마나 추가할 수 있나요?
정확한 숫자는 브라우저마다 다릅니다. 현재 추가된 데이터의 양을 쿼리할 수 없으므로 추가하는 양을 직접 추적해야 합니다. 주목해야 할 사항은 다음과 같습니다. 이메일을 작성하는 시점에 수집할 수 있는 최선의 데이터입니다. Chrome의 경우 이 숫자는 상한선이므로 시스템에 메모리 부족 문제가 발생하면 더 작을 수 있습니다.
Chrome | Chromecast* | Firefox | Safari | Edge | |
---|---|---|---|---|---|
동영상 | 150MB | 30MB | 100MB | 290MB | 알 수 없음 |
오디오 | 12MB | 2MB | 15MB | 14MB | 알 수 없음 |
- 또는 메모리가 제한된 기타 Chrome 기기
그러면 어떻게 해야 하나요?
지원되는 데이터의 양은 매우 다양하며 SourceBuffer
에서 데이터의 양을 찾을 수 없으므로 QuotaExceededError
를 처리하여 간접적으로 가져와야 합니다. 이제 몇 가지 방법을 살펴보겠습니다.
QuotaExceededError
를 처리하는 방법에는 여러 가지가 있습니다. 실제로는 하나 이상의 접근 방식을 조합하는 것이 가장 좋습니다. HTMLMediaElement.currentTime
을 초과하여 가져오고 추가하려는 양에 따라 작업을 기반으로 하고 QuotaExceededError
에 따라 크기를 조정하는 방식을 취해야 합니다. 또한 mpd 파일(MPEG-DASH) 또는 m3u8 파일(HLS)과 같은 매니페스트를 사용하면 버퍼에 추가하는 데이터를 추적하는 데 도움이 됩니다.
이제 QuotaExceededError
를 처리하는 몇 가지 접근 방식을 살펴보겠습니다.
- 불필요한 데이터를 삭제하고 다시 추가합니다.
- 더 작은 프래그먼트를 추가합니다.
- 재생 해상도를 낮춥니다.
이 두 가지를 함께 사용할 수도 있지만 하나씩 설명하겠습니다.
불필요한 데이터 삭제 및 다시 추가
사실 이 메서드는 '가장 빨리 사용될 가능성이 낮은 데이터를 삭제한 다음 곧 사용될 가능성이 높은 데이터의 추가를 다시 시도'해야 합니다. 제목이 너무 깁니다. 무슨 말인지 기억해 두셔야 해요.
최근 데이터를 삭제하는 것은 SourceBuffer.remove()
를 호출하는 것만큼 간단하지 않습니다. SourceBuffer
에서 데이터를 삭제하려면 업데이트 플래그가 false여야 합니다. 지원되지 않는 경우 데이터를 삭제하기 전에 SourceBuffer.abort()
를 호출합니다.
SourceBuffer.remove()
를 호출할 때 유의해야 할 사항이 몇 가지 있습니다.
- 이 경우 재생에 부정적인 영향을 미칠 수 있습니다. 예를 들어 동영상을 곧 다시 재생하거나 반복하려면 동영상의 시작 부분을 삭제하지 않는 것이 좋습니다. 마찬가지로 나 또는 사용자가 데이터를 삭제한 동영상 부분으로 탐색하는 경우 탐색을 충족하기 위해 해당 데이터를 다시 추가해야 합니다.
- 가능한 한 보수적으로 삭제합니다.
currentTime
또는 그 이전의 키프레임에서 시작되는 현재 재생 중인 프레임 그룹을 삭제하면 재생 지연이 발생할 수 있으므로 주의하세요. 이러한 정보를 매니페스트에서 사용할 수 없는 경우 웹 앱에 의해 바이트스트림에서 파싱되어야 할 수도 있습니다. 미디어 매니페스트 또는 미디어의 키프레임 간격에 대한 앱 지식을 사용하면 현재 재생 중인 미디어를 삭제하지 않도록 앱에서 삭제 범위를 선택하는 데 도움이 될 수 있습니다. 삭제하는 항목이 무엇이든 현재 재생 중인 사진 그룹이나 그 이후의 처음 몇 개는 삭제하지 마세요. 일반적으로 미디어가 더 이상 필요하지 않다고 확신하지 않는 한 현재 시간 이후부터는 삭제하지 않습니다. 재생 헤드 근처에서 삭제하면 중단될 수 있습니다. - Safari 9 및 Safari 10이
SourceBuffer.abort()
를 올바르게 구현하지 않습니다. 오히려 오류를 발생시켜 재생을 중단시킵니다. 다행히 여기와 여기에 공개 버그 추적기가 있습니다. 그때까지는 어떻게든 이 문제를 해결해야 합니다. Shaka Player는 이러한 버전의 Safari에서 빈abort()
함수를 스텁하여 이를 실행합니다.
더 작은 프래그먼트 추가
아래에 절차를 보여드렸습니다. 이 방법은 모든 경우에 작동하지 않을 수 있지만, 더 작은 청크의 크기를 필요에 맞게 조정할 수 있다는 이점이 있습니다. 또한 네트워크로 돌아가지 않아도 되므로 일부 사용자에게는 추가 데이터 비용이 발생할 수 있습니다.
const pieces = new Uint8Array([data]);
(function appendFragments(pieces) {
if (sourceBuffer.updating) {
return;
}
pieces.forEach(piece => {
try {
sourceBuffer.appendBuffer(piece);
}
catch e {
if (e.name !== 'QuotaExceededError') {
throw e;
}
// Reduction schedule: 80%, 60%, 40%, 20%, 16%, 12%, 8%, 4%, fail.
const reduction = pieces[0].byteLength * 0.8;
if (reduction / data.byteLength < 0.04) {
throw new Error('MediaSource threw QuotaExceededError too many times');
}
const newPieces = [
pieces[0].slice(0, reduction),
pieces[0].slice(reduction, pieces[0].byteLength)
];
pieces.splice(0, 1, newPieces[0], newPieces[1]);
appendBuffer(pieces);
}
});
})(pieces);
재생 해상도 낮추기
이는 최근 데이터를 삭제하고 다시 추가하는 것과 유사합니다. 사실 두 작업은 함께 실행할 수 있지만 아래 예에서는 해상도만 낮추는 방법을 보여줍니다.
이 기법을 사용할 때 유의해야 할 몇 가지 사항이 있습니다.
- 새 초기화 세그먼트를 추가해야 합니다. 표현을 변경할 때마다 이 작업을 실행해야 합니다. 새 초기화 세그먼트는 다음 미디어 세그먼트를 위한 것이어야 합니다.
- 추가된 미디어의 프레젠테이션 타임스탬프는 버퍼에 있는 데이터의 타임스탬프와 최대한 일치해야 하지만 점프할 수는 없습니다. 버퍼링된 데이터를 겹치면 브라우저에 따라 끊김이나 잠시 중단이 발생할 수 있습니다. 추가하는 항목과 관계없이 재생 헤드를 겹치지 마세요. 그러면 오류가 발생합니다.
- 탐색 시 재생이 중단될 수 있습니다. 특정 위치로 이동하여 거기서 재생을 재개하고 싶을 수 있습니다. 이렇게 하면 탐색이 완료될 때까지 재생 중단이 발생한다는 점에 유의하세요.