Signatur
Beschreibung
Der Konstruktor ManagedMediaSource() erzeugt ein neues ManagedMediaSource-Objekt. Anfangs hat es keine zugeordneten Quellpuffer, und sein readyState ist "closed". ManagedMediaSource erbt von MediaSource und bietet damit dieselbe API für Media Source Extensions (MSE): Man hängt es an ein <video>- oder <audio>-Element, legt nach dem Ereignis sourceopen mit addSourceBuffer() Puffer an und füllt sie mit Mediensegmenten, etwa bei adaptivem Streaming (HLS/DASH mit fMP4).
Anders als bei MediaSource hat der Browser bei ManagedMediaSource mehr Kontrolle. Er darf gepufferte Daten selbst entfernen, zum Beispiel wenn der Speicher knapp wird. Außerdem sagt er der Anwendung über die Eigenschaft streaming und die Ereignisse startstreaming und endstreaming, wann sie neue Daten laden soll. So kann das Gerät das Funkmodul länger schlafen lassen, was auf Mobilgeräten Akku spart. Deshalb ist ManagedMediaSource auf dem iPhone die einzige MSE-Variante. Das klassische MediaSource gibt es dort nicht.
In der Praxis prüft man zuerst, ob window.ManagedMediaSource existiert, und greift sonst auf MediaSource zurück. Die Anwendung sollte nur Daten anhängen, solange streaming den Wert true hat. Außerdem sollte sie das Ereignis bufferedchange der ManagedSourceBuffer-Objekte beobachten, weil der Browser gepufferte Bereiche auch ohne Zutun der Anwendung entfernen kann.
Rückgabewert
ManagedMediaSource-Instanz mit readyState === "closed" und leerer sourceBuffers-Liste.Beispiele
Funktionserkennung mit Rückfall auf MediaSource
const MSClass = window.ManagedMediaSource ?? window.MediaSource;
if (!MSClass) {
console.log('Kein MSE-Support – native Wiedergabe verwenden');
} else {
const source = new MSClass();
console.log(source.constructor.name, source.readyState);
}
An ein Video-Element anhängen und Puffer anlegen
const video = document.querySelector('video');
const source = new ManagedMediaSource();
// Ohne AirPlay-Alternative Pflicht, sonst feuert 'sourceopen' nicht
video.disableRemotePlayback = true;
video.src = URL.createObjectURL(source);
source.addEventListener('sourceopen', async () => {
const mime = 'video/mp4; codecs="avc1.64001f, mp4a.40.2"';
if (!ManagedMediaSource.isTypeSupported(mime)) return;
const buffer = source.addSourceBuffer(mime);
const init = await fetch('/media/init.mp4').then(r => r.arrayBuffer());
buffer.appendBuffer(init);
console.log('Init-Segment angehängt');
}, { once: true });
Nur nachladen, wenn der Browser es wünscht
const source = new ManagedMediaSource();
const video = document.querySelector('video');
video.disableRemotePlayback = true;
video.src = URL.createObjectURL(source);
const segments = ['/media/seg1.m4s', '/media/seg2.m4s', '/media/seg3.m4s'];
let buffer;
const loadNext = async () => {
if (!source.streaming || !segments.length || buffer.updating) return;
const data = await fetch(segments.shift()).then(r => r.arrayBuffer());
buffer.appendBuffer(data);
};
source.addEventListener('sourceopen', () => {
buffer = source.addSourceBuffer('video/mp4; codecs="avc1.64001f"');
buffer.addEventListener('updateend', loadNext);
buffer.addEventListener('bufferedchange', (e) => {
console.log('Entfernte Bereiche:', e.removedRanges.length);
});
loadNext();
});
source.addEventListener('startstreaming', () => {
console.log('Browser fordert Daten an');
loadNext();
});
source.addEventListener('endstreaming', () => console.log('Nachladen pausieren'));
// Wichtig · Fallstricke
- Browser-Unterstützung:
ManagedMediaSourcegibt es in Safari ab Version 17 (macOS) bzw. 17.1 (iOS/iPadOS). Chrome und Firefox unterstützen die Schnittstelle derzeit nicht. Deshalb immer die Funktion erkennen und aufMediaSourcezurückfallen. - AirPlay/Remote Playback: Unter Safari feuert
sourceopennur, wenn man entwedervideo.disableRemotePlayback = truesetzt oder über<source>eine Alternative für AirPlay angibt, etwa einen HLS-Stream. Das wird am häufigsten übersehen. - Daten können verschwinden: Der Browser darf gepufferte Bereiche selbst entfernen. Man sollte sich also nicht darauf verlassen, dass bereits angehängte Segmente erhalten bleiben. Stattdessen
bufferedchangeauswerten und entfernte Bereiche bei Bedarf neu laden. streamingbeachten: Wer auch beistreaming === falseweiter Daten anhängt, verschenkt den Energiespareffekt. Der Browser kann solche Daten außerdem wieder verwerfen.- Der Konstruktor erwartet keine Argumente. Ohne
newaufgerufen, wirft er einenTypeError. - Nicht mehr benötigte Objekt-URLs mit
URL.revokeObjectURL()freigeben.