Signatur
Beschreibung
Die Eigenschaft gatheringState eines RTCIceTransport-Objekts zeigt, wie weit der ICE-Agent beim Sammeln lokaler Kandidaten (ICE candidates) für genau diesen Transport ist. Anders als RTCPeerConnection.iceGatheringState, das alle Transporte einer Verbindung zusammenfasst, gilt dieser Wert nur für einen einzelnen Transport, etwa den Transport eines bestimmten RTCRtpSender.
Mögliche Werte:
"new": Der Transport ist neu angelegt, das Sammeln hat noch nicht begonnen."gathering": Der ICE-Agent sammelt gerade Kandidaten (Host, STUN/Server-Reflexive, TURN/Relay)."complete": Das Sammeln ist abgeschlossen. Kommt später eine ICE-Neuverhandlung (ICE restart) oder ändert sich die Netzwerkschnittstelle, kann der Wert wieder auf"gathering"springen.
Sie können den Wert direkt abfragen oder auf das Ereignis gatheringstatechange des Transports hören. So erkennen Sie zum Beispiel, wann für einen bestimmten Medienpfad alle Kandidaten da sind. Beim „Non-Trickle“-Signalisieren können Sie erst dann die vollständige SDP verschicken. Außerdem hilft der Wert bei der Diagnose von Verbindungsproblemen.
Rückgabewert
Beispiele
Sammelstatus eines Sender-Transports abfragen
const pc = new RTCPeerConnection({ iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] });
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const sender = pc.addTrack(stream.getAudioTracks()[0], stream);
await pc.setLocalDescription(await pc.createOffer());
// Der Transport existiert erst nach setLocalDescription
const iceTransport = sender.transport?.iceTransport;
console.log('Sammelstatus:', iceTransport?.gatheringState);
Auf gatheringstatechange reagieren
const watchGathering = (iceTransport) => {
const onChange = () => {
console.log('Neuer Sammelstatus:', iceTransport.gatheringState);
if (iceTransport.gatheringState === 'complete') {
console.log('Alle lokalen Kandidaten gesammelt.');
}
};
iceTransport.addEventListener('gatheringstatechange', onChange);
// Aufräumfunktion zurückgeben
return () => iceTransport.removeEventListener('gatheringstatechange', onChange);
};
const pc = new RTCPeerConnection();
const transceiver = pc.addTransceiver('video');
await pc.setLocalDescription(await pc.createOffer());
const stop = watchGathering(transceiver.sender.transport.iceTransport);
Promise: warten, bis das Sammeln abgeschlossen ist
const waitForGatheringComplete = (iceTransport, timeoutMs = 5000) =>
new Promise((resolve, reject) => {
if (iceTransport.gatheringState === 'complete') return resolve();
const timer = setTimeout(() => reject(new Error('ICE-Sammeln: Zeitüberschreitung')), timeoutMs);
iceTransport.ongatheringstatechange = () => {
if (iceTransport.gatheringState === 'complete') {
clearTimeout(timer);
iceTransport.ongatheringstatechange = null;
resolve();
}
};
});
const pc = new RTCPeerConnection();
const { sender } = pc.addTransceiver('audio');
await pc.setLocalDescription(await pc.createOffer());
await waitForGatheringComplete(sender.transport.iceTransport);
// Jetzt enthält localDescription alle Kandidaten (Non-Trickle-Signalisierung)
console.log(pc.localDescription.sdp.includes('a=candidate'));
// Wichtig · Fallstricke
- Browser-Kompatibilität:
RTCIceTransportgibt es in Chromium-Browsern und Safari. Firefox stellt die Schnittstelle bisher nicht bereit, dort istRTCDtlsTransport.iceTransportnicht verfügbar. Nutzen Sie dortRTCPeerConnection.iceGatheringStateals Ausweichlösung und prüfen Sie vorher, ob das Feature vorhanden ist. sender.transportbzw.receiver.transportistnull, solange keine lokale oder entfernte Beschreibung gesetzt wurde. Den Transport also erst nachsetLocalDescription()auslesen.- Bei
bundlePolicy: "max-bundle"(dem üblichen Fall) teilen sich alle Medienspuren einen Transport, daher gibt es nur einen Sammelstatus. - Der Wert kann von
"complete"wieder auf"gathering"wechseln, etwa nachrestartIce()oder bei einem Netzwechsel. Verlassen Sie sich also nicht darauf, dass"complete"endgültig ist. - Ohne STUN/TURN-Server ist das Sammeln oft sehr schnell fertig. Mit nicht erreichbaren Servern kann es dagegen lange dauern, deshalb immer eine Zeitbegrenzung setzen.