Signatur
Beschreibung
Die Methode getSynchronizationSources() eines RTCRtpReceiver liefert für jede Synchronisationsquelle (SSRC, Synchronization Source) einen Eintrag, von der in den letzten zehn Sekunden RTP-Pakete eingegangen sind. Eine SSRC steht für einen einzelnen RTP-Datenstrom, z. B. das Mikrofon oder die Kamera einer entfernten Person.
Jedes zurückgegebene Objekt enthält unter anderem source (die SSRC-Kennung als Zahl), timestamp (Zeitpunkt, zu dem das letzte Paket dieser Quelle abgespielt wurde, als DOMHighResTimeStamp), rtpTimestamp (RTP-Zeitstempel des Pakets), bei Audio audioLevel (0,0 bis 1,0) sowie voiceActivityFlag, sofern die Gegenseite die entsprechende RTP-Header-Erweiterung sendet.
Typische Anwendungsfälle sind Pegelanzeigen („wer spricht gerade?“), die Erkennung inaktiver Streams oder Diagnosewerkzeuge. Weil die Methode synchron und ohne Aufwand für den Aufrufer ist, eignet sie sich gut zum regelmäßigen Abfragen, z. B. in requestAnimationFrame oder per setInterval.
Für gemischte Streams (etwa aus einem Konferenz-Mixer/MCU) ergänzt getContributingSources() die Information um die CSRCs der einzelnen Beitragenden.
Rückgabewert
source, timestamp, rtpTimestamp, optional audioLevel und voiceActivityFlag. Leeres Array, wenn noch keine Pakete eingegangen sind.Beispiele
Synchronisationsquellen eines eingehenden Tracks auslesen
const pc = new RTCPeerConnection();
pc.addEventListener('track', ({ receiver }) => {
// Nach kurzer Zeit sind Pakete eingegangen
setTimeout(() => {
const sources = receiver.getSynchronizationSources();
for (const s of sources) {
console.log(`SSRC ${s.source}, zuletzt abgespielt: ${s.timestamp.toFixed(0)} ms, RTP-Zeit: ${s.rtpTimestamp}`);
}
}, 2000);
});
Live-Pegelanzeige für entferntes Audio
const meter = document.querySelector('#pegel'); // <meter min="0" max="1">
const startLevelMeter = (receiver) => {
const update = () => {
const [src] = receiver.getSynchronizationSources();
meter.value = src?.audioLevel ?? 0;
requestAnimationFrame(update);
};
requestAnimationFrame(update);
};
pc.addEventListener('track', ({ track, receiver }) => {
if (track.kind === 'audio') startLevelMeter(receiver);
});
Aktive Sprecher über alle Empfänger ermitteln
const getActiveSpeakers = (pc, threshold = 0.05) => {
const now = performance.now();
return pc.getReceivers()
.filter((r) => r.track.kind === 'audio')
.flatMap((r) => r.getSynchronizationSources()
.filter((s) => now - s.timestamp < 500 && (s.audioLevel ?? 0) > threshold)
.map((s) => ({ trackId: r.track.id, ssrc: s.source, level: s.audioLevel })));
};
setInterval(() => console.log(getActiveSpeakers(pc)), 1000);
// Wichtig · Fallstricke
- Zehn-Sekunden-Fenster: Quellen, von denen länger als zehn Sekunden nichts kam, verschwinden aus dem Array. Ein leeres Array bedeutet also nicht zwingend einen Fehler, sondern oft nur „noch/gerade keine Pakete“.
audioLevelundvoiceActivityFlagsind nur vorhanden, wenn die Gegenseite die RTP-Header-Erweiterung ssrc-audio-level (RFC 6464) aushandelt; bei Video fehlen sie immer. Zudem istaudioLevellinear skaliert (aus dBov umgerechnet) – für eine gehörrichtige Anzeige ggf. selbst nachskalieren.timestampnutzt dieselbe Zeitbasis wieperformance.now(), nichtDate.now().voiceActivityFlagwird nicht von allen Browsern befüllt (u. a. in Chrome oftundefined).- Für genaue Statistiken (Paketverlust, Jitter) ist
RTCPeerConnection.getStats()besser geeignet;getSynchronizationSources()ist auf leichtgewichtige Echtzeit-Abfragen ausgelegt. - Browser-Unterstützung: in allen aktuellen Browsern verfügbar; ältere Safari-Versionen (< 12.1) und alte Edge-Versionen (EdgeHTML) unterstützen sie nicht.