Si trabajas con extensiones de fuente de medios (MSE), con el tiempo deberás lidiar con un búfer demasiado lleno. Cuando esto suceda, recibirás lo que se denomina QuotaExceededError
. En este artículo, abordaré algunas de las
formas de abordarlo.
¿Qué es QuotaExceededError?
Básicamente, QuotaExceededError
es lo que obtienes si intentas agregar demasiados datos
a tu objeto SourceBuffer
. (Agregar más objetos SourceBuffer
a un elemento MediaSource
superior también puede generar este error). Eso está fuera del alcance de este artículo). Si SourceBuffer
tiene demasiados datos, llamar a SourceBuffer.appendBuffer()
activará el siguiente mensaje en la ventana de la consola de Chrome.

Hay algunos aspectos que debes tener en cuenta. Primero, observa que el nombre QuotaExceededError
no aparece en ningún lugar del mensaje. Para verlo, establece un punto de interrupción en una ubicación en la que puedas detectar el error y examinarlo en la ventana de supervisión o alcance. A continuación, te muestro cómo hacerlo.

En segundo lugar, no hay una forma definitiva de saber cuántos datos puede controlar SourceBuffer
.
Comportamiento en otros navegadores
En el momento de escribir este artículo, Safari no arroja un QuotaExceededError
en muchas de sus compilaciones. En su lugar, quita fotogramas con un algoritmo de dos pasos y se detiene si hay suficiente espacio para controlar el appendBuffer()
. Primero, libera fotogramas de entre 0 y 30 segundos antes de la hora actual en segmentos de 30 segundos. A continuación, libera fotogramas en fragmentos de 30 segundos desde la duración hacia atrás hasta 30 segundos después de currentTime
. Puedes obtener más información sobre esto en un cambio de Webkit de 2014.
Por fortuna, junto con Chrome, Edge y Firefox arrojan este error. Si usas otro navegador, deberás realizar tus propias pruebas. Si bien es probable que no sea lo que compilarías para un reproductor multimedia real, la prueba de límite de búfer de origen de François Beaufort al menos te permite observar el comportamiento.
¿Cuántos datos puedo adjuntar?
La cantidad exacta varía según el navegador. Como no puedes consultar la cantidad de datos que se agregaron, deberás hacer un seguimiento de la cantidad que agregas. En cuanto a lo que debes tener en cuenta, estos son los mejores datos que puedo recopilar en el momento de escribir este artículo. En el caso de Chrome, estos números son límites superiores, lo que significa que pueden ser más pequeños cuando el sistema encuentra presión de memoria.
Chrome | Chromecast* | Firefox | Safari | Edge | |
---|---|---|---|---|---|
Video | 150 MB | 30 MB | 100 MB | 290 MB | Desconocido |
Audio | 12 MB | 2 MB | 15 MB | 14 MB | Desconocido |
- O bien, cualquier otro dispositivo Chrome con memoria limitada.
¿Qué debo hacer?
Dado que la cantidad de datos compatibles varía mucho y no puedes encontrar la cantidad de datos en un SourceBuffer
, debes obtenerla de forma indirecta controlando el QuotaExceededError
. Ahora, veamos algunas formas de hacerlo.
Existen varios enfoques para lidiar con QuotaExceededError
. En realidad, lo mejor es una combinación de uno o más enfoques. Tu enfoque debe basarse en la cantidad que recuperas y en la que intentas agregar más allá de HTMLMediaElement.currentTime
y ajustar ese tamaño según QuotaExceededError
. Además, usar un manifiesto de algún tipo, como un archivo mpd (MPEG-DASH) o un archivo m3u8 (HLS), puede ayudarte a hacer un seguimiento de los datos que agregas al búfer.
Ahora, veamos varios enfoques para abordar el QuotaExceededError
.
- Quita los datos innecesarios y vuelve a adjuntarlos.
- Agrega fragmentos más pequeños.
- Disminuye la resolución de reproducción.
Aunque se pueden usar en combinación, hablaré de cada una por separado.
Quita los datos innecesarios y vuelve a adjuntarlos
En realidad, se debería llamar "Quita los datos que es menos probable que se usen pronto y, luego, vuelve a intentar agregar los datos que es probable que se usen pronto". Ese título es demasiado largo. Solo tendrás que recordar lo que realmente quiero decir.
Quitar datos recientes no es tan simple como llamar a SourceBuffer.remove()
. Para quitar datos de SourceBuffer
, su marca de actualización debe ser falsa. Si no es así, llama a SourceBuffer.abort()
antes de quitar los datos.
Hay algunos aspectos que debes tener en cuenta cuando llames a SourceBuffer.remove()
.
- Esto podría tener un impacto negativo en la reproducción. Por ejemplo, si quieres que el video se vuelva a reproducir o se repita pronto, no es recomendable quitar el comienzo. Del mismo modo, si tú o el usuario saltan a una parte del video en la que quitaste datos, deberás volver a agregarlos para satisfacer ese salto.
- Quita la mayor cantidad posible de vello. Ten cuidado de no quitar el grupo de fotogramas que se está reproduciendo actualmente y que comienza en el fotograma clave en
currentTime
o antes, ya que esto podría provocar que la reproducción se detenga. Es posible que la app web deba analizar esa información del flujo de bytes si no está disponible en el manifiesto. Un manifiesto multimedia o el conocimiento de la app sobre los intervalos de fotogramas clave en el contenido multimedia pueden ayudar a guiar la elección de los rangos de eliminación de la app para evitar que se quite el contenido multimedia que se está reproduciendo. No quites el grupo de imágenes que se está reproduciendo ni las primeras imágenes después de él. Por lo general, no quites el contenido más allá de la hora actual, a menos que tengas la seguridad de que ya no lo necesitas. Si lo quitas cerca del cabezal de reproducción, es posible que se produzca una detención. - Safari 9 y Safari 10 no implementan correctamente
SourceBuffer.abort()
. De hecho, arrojan errores que detienen la reproducción. Afortunadamente, hay servicios de seguimiento de errores abiertos aquí y aquí. Mientras tanto, deberás solucionar este problema de alguna manera. Shaka Player lo hace con la creación de un stub de una funciónabort()
vacía en esas versiones de Safari.
Cómo adjuntar fragmentos más pequeños
A continuación, te muestro el procedimiento. Es posible que esto no funcione en todos los casos, pero tiene la ventaja de que el tamaño de los fragmentos más pequeños se puede ajustar para satisfacer tus necesidades. Tampoco es necesario volver a la red, lo que podría generar costos de datos adicionales para algunos usuarios.
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);
Baja la resolución de reproducción
Esto es similar a quitar datos recientes y volver a agregarlos. De hecho, se pueden hacer juntos, aunque en el siguiente ejemplo solo se muestra cómo bajar la resolución.
Hay algunos aspectos que debes tener en cuenta cuando uses esta técnica:
- Debes agregar un nuevo segmento de inicialización. Debes hacerlo cada vez que cambias las representaciones. El nuevo segmento de inicialización debe ser para los segmentos de contenido multimedia que siguen.
- La marca de tiempo de presentación del contenido multimedia adjunto debe coincidir con la marca de tiempo de los datos en el búfer lo más cerca posible, pero no debe avanzar. La superposición de los datos almacenados en búfer puede causar una interrupción o una detención breve, según el navegador. Independientemente de lo que agregues, no superpongas el cabezal de reproducción, ya que esto generará errores.
- Es posible que el salto interrumpa la reproducción. Es posible que quieras buscar una ubicación específica y reanudar la reproducción desde allí. Ten en cuenta que esto provocará una interrupción de la reproducción hasta que se complete el salto.