Signatur
Beschreibung
Die schreibgeschützte Eigenschaft candidate der Schnittstelle RTCIceCandidate liefert einen String, der den Kandidaten im Detail beschreibt. Das Format entspricht dem candidate-Attribut aus SDP (RFC 5245 bzw. RFC 8839), allerdings ohne das Präfix a=. Ein typischer Wert ist candidate:4234997325 1 udp 2043278322 192.168.0.56 44323 typ host.
Der String enthält alle wichtigen Merkmale des Kandidaten, die zusätzlich auch als eigene Eigenschaften verfügbar sind:
- foundation – Kennung zum Gruppieren gleichartiger Kandidaten (
foundation) - component –
1= RTP,2= RTCP (component) - transport –
udpodertcp(protocol) - priority, Adresse und Port (
priority,address,port) - typ –
host,srflx,prflxoderrelay(type) - optional
raddr/rport(relatedAddress,relatedPort) undtcptype
In der Praxis wird candidate vor allem beim Trickle ICE verwendet: Im Handler des icecandidate-Events wird der Kandidat (meist per candidate.toJSON()) über den Signalisierungskanal an die Gegenstelle geschickt, die ihn mit RTCPeerConnection.addIceCandidate() hinzufügt. Ein leerer String "" signalisiert dabei das Ende der Kandidatensammlung für eine Generation (end-of-candidates).
Rückgabewert
a=). Ein leerer String "" kennzeichnet einen end-of-candidates-Hinweis.Beispiele
Kandidaten beim Sammeln protokollieren und an die Gegenstelle senden
const pc = new RTCPeerConnection({
iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
});
// Platzhalter für einen echten Signalisierungskanal (z. B. WebSocket)
const signaling = { send: (msg) => console.log('Sende:', msg) };
pc.addEventListener('icecandidate', (event) => {
if (event.candidate) {
console.log('Kandidat:', event.candidate.candidate);
signaling.send(JSON.stringify({ ice: event.candidate.toJSON() }));
} else {
console.log('ICE-Sammlung abgeschlossen');
}
});
pc.createDataChannel('chat');
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
Kandidat aus einem SDP-String erzeugen und auslesen
const ice = new RTCIceCandidate({
candidate: 'candidate:842163049 1 udp 1677729535 203.0.113.7 51234 typ srflx raddr 192.168.1.20 rport 51234',
sdpMid: '0',
sdpMLineIndex: 0
});
console.log(ice.candidate);
console.log(ice.type, ice.protocol, ice.address, ice.port);
Nur TURN-Relay-Kandidaten weiterleiten (Debugging)
const pc = new RTCPeerConnection({
iceServers: [{ urls: 'turn:turn.example.com:3478', username: 'user', credential: 'geheim' }]
});
pc.onicecandidate = ({ candidate }) => {
if (!candidate || candidate.candidate === '') return;
// Fallback per Regex, falls candidate.type nicht verfügbar ist
const typ = candidate.type ?? candidate.candidate.match(/ typ (\w+)/)?.[1];
if (typ === 'relay') {
console.log('Relay-Kandidat:', candidate.candidate);
}
};
pc.createDataChannel('test');
await pc.setLocalDescription(await pc.createOffer());
// Wichtig · Fallstricke
- Schreibgeschützt: Der Wert wird nur über den Konstruktor
new RTCIceCandidate({ candidate, sdpMid, sdpMLineIndex })gesetzt; Zuweisungen werden ignoriert. - Leerer String vs.
null: Imicecandidate-Event bedeutetevent.candidate === nulldas Ende aller Sammlungen. Ein Kandidat mitcandidate === ""ist ein end-of-candidates-Hinweis und sollte ebenfalls anaddIceCandidate()weitergegeben werden, nicht verworfen. - Kein
a=-Präfix: Wer Kandidaten manuell in SDP einfügt, mussa=voranstellen; umgekehrt beim Parsen entfernen. - Datenschutz: Moderne Browser verschleiern lokale Host-Adressen mit mDNS-Namen (z. B.
3f1c….local), solange keine Kamera-/Mikrofonfreigabe besteht. Der String kann trotzdem öffentliche IPs (srflx) preisgeben – nicht unnötig protokollieren oder an Dritte weitergeben. - Nur
candidatesenden reicht nicht: FüraddIceCandidate()werden auchsdpMid/sdpMLineIndexbenötigt – am einfachsten das ganze Objekt pertoJSON()serialisieren. - Die Einzeleigenschaften (
type,address, …) werden in älteren Browsern (v. a. älteres Firefox) teils nicht unterstützt; dann bleibt nur das Parsen descandidate-Strings.