Signatur
Beschreibung
Die schreibgeschützte Eigenschaft scalabilityMode eines RTCOutboundRtpStreamStats-Objekts gibt an, mit welchem Skalierungsmodus (Scalable Video Coding, SVC) der Encoder den ausgehenden Video-Stream erzeugt. Der Wert ist eine Zeichenkette aus der Spezifikation WebRTC-SVC, etwa "L1T2", "L1T3", "L3T3", "L2T2_KEY" oder "S2T1".
Aufbau des Bezeichners: L steht für die Anzahl der räumlichen Schichten (Spatial Layers) mit gegenseitiger Abhängigkeit und S für unabhängige räumliche Schichten (Simulcast-ähnlich innerhalb eines Streams). T gibt die Anzahl der zeitlichen Schichten (Temporal Layers) an. Zusätze wie _KEY oder _KEY_SHIFT beschreiben, wie die Schichten über Keyframes voneinander abhängen. "L1T1" heißt also: keine Skalierung.
Gesetzt wird der Modus über sendEncodings[].scalabilityMode bei RTCPeerConnection.addTransceiver() oder später über RTCRtpSender.setParameters(). Welche Modi ein Codec unterstützt, verrät RTCRtpSender.getCapabilities("video").codecs[].scalabilityModes. Die Statistik-Eigenschaft zeigt, welcher Modus tatsächlich aktiv ist. Das ist nützlich, um die Konfiguration zu prüfen, Fehler in SFU-Setups zu finden (Selective Forwarding Unit) oder die Qualität zu überwachen.
Rückgabewert
"L1T3"). undefined, wenn kein Modus konfiguriert ist, der Stream kein Video ist oder der Browser die Eigenschaft nicht unterstützt.Beispiele
Skalierungsmodus aus getStats() auslesen
const logScalabilityModes = async (pc) => {
const report = await pc.getStats();
report.forEach((stats) => {
if (stats.type === 'outbound-rtp' && stats.kind === 'video') {
console.log(`SSRC ${stats.ssrc}: ${stats.scalabilityMode ?? 'kein SVC konfiguriert'}`);
}
});
};
// pc ist eine bestehende, verbundene RTCPeerConnection
await logScalabilityModes(pc);
SVC-Modus setzen und Übernahme überprüfen
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
const [track] = stream.getVideoTracks();
const pc = new RTCPeerConnection();
// Prüfen, ob ein Codec L1T3 unterstützt
const { codecs } = RTCRtpSender.getCapabilities('video');
const supportsL1T3 = codecs.some((c) => c.scalabilityModes?.includes('L1T3'));
const transceiver = pc.addTransceiver(track, {
direction: 'sendonly',
sendEncodings: [supportsL1T3 ? { scalabilityMode: 'L1T3' } : {}]
});
// ... Signalisierung / Verbindungsaufbau ...
const stats = await transceiver.sender.getStats();
for (const s of stats.values()) {
if (s.type === 'outbound-rtp') {
console.log('Aktiver Modus:', s.scalabilityMode);
}
}
Moduswechsel zur Laufzeit überwachen
const watchScalabilityMode = (sender, intervalMs = 2000) => {
let last;
const timer = setInterval(async () => {
const stats = await sender.getStats();
for (const s of stats.values()) {
if (s.type !== 'outbound-rtp') continue;
if (s.scalabilityMode !== last) {
console.log(`Modus geändert: ${last ?? '–'} → ${s.scalabilityMode ?? '–'}`);
last = s.scalabilityMode;
}
}
}, intervalMs);
return () => clearInterval(timer);
};
const stop = watchScalabilityMode(pc.getSenders()[0]);
// Modus zur Laufzeit ändern
const params = pc.getSenders()[0].getParameters();
params.encodings[0].scalabilityMode = 'L1T2';
await pc.getSenders()[0].setParameters(params);
// Wichtig · Fallstricke
- Browser-Kompatibilität: Die Eigenschaft ist nicht Baseline. Chromium-basierte Browser unterstützen sie (ab etwa Version 111). In Firefox und Safari fehlt sie teilweise oder ganz. Prüfe deshalb immer auf
undefined, zum Beispiel mit?? 'L1T1'oder einem Hinweistext. - Die Eigenschaft gibt es nur für
type === "outbound-rtp"mitkind === "video". Audio-Streams haben keinen Skalierungsmodus. - Nicht jeder Codec unterstützt jeden Modus. VP8 kennt nur temporale Schichten (
L1T*). Räumliche Schichten (L2/L3) gibt es in der Regel nur bei VP9 und AV1. Ein nicht unterstützter Modus inaddTransceiver()odersetParameters()löst eineOperationErroraus oder wird ignoriert. - Der gemeldete Wert kann von der Anforderung abweichen, etwa wenn der Encoder (zum Beispiel ein Hardware-Encoder) auf einen anderen Modus zurückfällt. Verlass dich deshalb auf die Statistik und nicht auf die gesetzten Parameter.
- Bei Simulcast mit mehreren
encodingsgibt es für jede Encoding ein eigenesoutbound-rtp-Objekt mit eigenemscalabilityMode. Zuordnen lassen sie sich überrid. - Häufige
getStats()-Aufrufe kosten Rechenzeit. Für die Überwachung reichen Intervalle von 1 bis 5 Sekunden.