Signatur
Beschreibung
setLocalDescription() übergibt der Verbindung die lokale Seite der SDP-Aushandlung, also das Angebot (offer) oder die Antwort (answer), die der eigene Peer an die Gegenstelle schickt. Erst danach wechselt die Verbindung in den passenden Signalisierungszustand (have-local-offer bzw. stable) und beginnt, ICE-Kandidaten zu sammeln, die über das Ereignis icecandidate gemeldet werden.
Seit der WebRTC-Überarbeitung für Perfect Negotiation lässt sich die Methode ohne Argument aufrufen. Der Browser erstellt dann je nach Signalisierungszustand selbst ein Angebot oder eine Antwort und setzt es. Das vermeidet Race Conditions zwischen createOffer()/createAnswer() und dem Setzen. Die klassische Variante übergibt ein zuvor erzeugtes Beschreibungsobjekt.
Die Methode gibt ein Promise zurück, das erfüllt wird, sobald die Beschreibung übernommen wurde. Danach steht sie in pc.localDescription und kann über den eigenen Signalisierungskanal (z. B. WebSocket) an den Peer gesendet werden.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $sessionDescription | RTCSessionDescriptionInit | RTCSessionDescription | automatisch erzeugtes Angebot bzw. Antwort | Objekt mit type ("offer", "answer", "pranswer" oder "rollback") und optional sdp. Wird es weggelassen oder fehlt sdp, erzeugt der Browser die passende Beschreibung selbst. |
Rückgabewert
InvalidStateError, InvalidModificationError oder OperationError.Beispiele
Angebot erstellen (moderne, parameterlose Variante)
const pc = new RTCPeerConnection({ iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] });
const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
stream.getTracks().forEach((track) => pc.addTrack(track, stream));
pc.onnegotiationneeded = async () => {
await pc.setLocalDescription(); // Browser erzeugt das Angebot selbst
console.log(pc.signalingState);
signaling.send(JSON.stringify({ description: pc.localDescription }));
};
Klassische Variante mit createOffer()
const pc = new RTCPeerConnection();
pc.addTransceiver('audio');
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
console.log(pc.localDescription.type);
Auf ein eingehendes Angebot antworten
signaling.onmessage = async ({ data }) => {
const { description } = JSON.parse(data);
if (description?.type === 'offer') {
await pc.setRemoteDescription(description);
await pc.setLocalDescription(); // erzeugt automatisch eine Antwort
signaling.send(JSON.stringify({ description: pc.localDescription }));
}
};
Perfect Negotiation: Kollision per Rollback auflösen
const handleOffer = async (description, polite) => {
const collision = pc.signalingState !== 'stable';
if (collision && !polite) return; // unhöflicher Peer ignoriert das Angebot
if (collision) {
await pc.setLocalDescription({ type: 'rollback' });
}
await pc.setRemoteDescription(description);
await pc.setLocalDescription();
signaling.send(JSON.stringify({ description: pc.localDescription }));
};
// Wichtig · Fallstricke
- Reihenfolge beachten: Eine Antwort darf erst gesetzt werden, nachdem das entfernte Angebot per
setRemoteDescription()übernommen wurde. Sonst folgt einInvalidStateError. - Die parameterlose Variante wird von allen aktuellen Browsern unterstützt (Chrome 80+, Firefox 75+, Safari 14.1+). Für ältere Browser müsst ihr
createOffer()/createAnswer()explizit aufrufen. - Die frühere Callback-Signatur
setLocalDescription(desc, successCb, errorCb)ist veraltet. Verwendet stattdessen das Promise. - SDP vor dem Setzen von Hand zu ändern („SDP-Munging“) ist fehleranfällig und nicht standardisiert. Nutzt dafür lieber
RTCRtpTransceiver.setCodecPreferences()oderRTCRtpSender.setParameters(). pc.localDescriptionkann sich durch später gesammelte ICE-Kandidaten noch ändern. Bei Trickle-ICE sendet ihr die Kandidaten deshalb einzeln übericecandidate.- WebRTC funktioniert nur in sicheren Kontexten (HTTPS). Der Signalisierungskanal ist nicht Teil der API und muss selbst abgesichert werden.