Start · Sprachen · JavaScript · Referenz · RTCPeerConnection.createAnswer()

RTCPeerConnection.createAnswer()

Methode

Erstellt eine SDP-Antwort (<code>type: "answer"</code>) auf ein zuvor als Remote-Beschreibung gesetztes Angebot eines entfernten Peers.

seit JavaScript Baseline: alle modernen Browser (Chrome 24+, Firef Kategorie: webapi

Signatur

RTCPeerConnection.prototype.createAnswer(options)

Beschreibung

createAnswer() ist die Gegenstück-Methode zu createOffer() in der Angebot/Antwort-Aushandlung von WebRTC. Der angerufene Peer erhält über einen eigenen Signalisierungskanal (z. B. WebSocket) das SDP-Angebot des Anrufers, setzt es mit setRemoteDescription() und erzeugt dann mit createAnswer() eine passende Antwort. Darin stehen die Codecs, Medienrichtungen, ICE-Zugangsdaten und DTLS-Fingerabdrücke, auf die sich die lokale Seite einlässt.

Die Methode gibt ein Promise zurück, das mit einem Objekt der Form { type: "answer", sdp: "..." } erfüllt wird. Diese Antwort wird nicht automatisch angewendet: Du musst sie selbst mit setLocalDescription() setzen und danach über die Signalisierung an den entfernten Peer schicken, der sie wiederum per setRemoteDescription() übernimmt.

In modernem Code kannst du createAnswer() oft ganz weglassen: Ein parameterloser Aufruf von setLocalDescription() im Zustand have-remote-offer erzeugt und setzt die Antwort automatisch (sogenannte „implizite Beschreibung“, Grundlage des Musters Perfect Negotiation). Den expliziten Aufruf brauchst du aber weiterhin, wenn du die SDP vor dem Setzen prüfen oder protokollieren willst.

Parameter

Name Typ Default Beschreibung
$options RTCAnswerOptions | object {} Optionales Einstellungsobjekt. Aktuell sind keine standardisierten Einträge definiert, die sich auf Antworten auswirken. Das veraltete Feld voiceActivityDetection wird von den meisten Browsern ignoriert.
$successCallback / failureCallback Function Veraltet: Alte Callback-Signatur createAnswer(successCallback, failureCallback). Nicht mehr verwenden, stattdessen das Promise nutzen.

Rückgabewert

Typ
Promise<RTCSessionDescriptionInit>
Beschreibung
Ein Promise, das mit einem Objekt { type: "answer", sdp: string } erfüllt wird. Wird mit einer InvalidStateError-DOMException zurückgewiesen, wenn kein Remote-Angebot gesetzt oder die Verbindung geschlossen ist, bzw. mit NotReadableError, wenn kein Zertifikat für DTLS erzeugt werden konnte.

Beispiele

Eingehendes Angebot beantworten (klassischer Ablauf)

const pc = new RTCPeerConnection({
  iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
});
const ws = new WebSocket('wss://signal.example.com');

// ICE-Kandidaten an die Gegenseite weiterreichen
pc.addEventListener('icecandidate', ({ candidate }) => {
  if (candidate) ws.send(JSON.stringify({ type: 'candidate', candidate }));
});

ws.addEventListener('message', async (event) => {
  const msg = JSON.parse(event.data);

  if (msg.type === 'offer') {
    // 1. Angebot des Anrufers übernehmen
    await pc.setRemoteDescription(msg);

    // 2. Eigene Medien hinzufügen (vor createAnswer!)
    const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
    stream.getTracks().forEach((track) => pc.addTrack(track, stream));

    // 3. Antwort erzeugen, lokal setzen und zurückschicken
    const answer = await pc.createAnswer();
    await pc.setLocalDescription(answer);
    ws.send(JSON.stringify(pc.localDescription));
    console.log('Antwort gesendet:', answer.type);
  } else if (msg.type === 'candidate') {
    await pc.addIceCandidate(msg.candidate);
  }
});
Antwort gesendet: answer

Vollständige Aushandlung lokal zwischen zwei Verbindungen

const caller = new RTCPeerConnection();
const callee = new RTCPeerConnection();

// Kandidaten direkt austauschen (ersetzt den Signalisierungsserver)
caller.onicecandidate = (e) => e.candidate && callee.addIceCandidate(e.candidate);
callee.onicecandidate = (e) => e.candidate && caller.addIceCandidate(e.candidate);

caller.createDataChannel('chat');

const offer = await caller.createOffer();
await caller.setLocalDescription(offer);
await callee.setRemoteDescription(offer);

const answer = await callee.createAnswer();
await callee.setLocalDescription(answer);
await caller.setRemoteDescription(answer);

console.log(callee.signalingState, caller.signalingState);
stable stable

Fehler bei falschem Zustand abfangen

const pc = new RTCPeerConnection();

try {
  // Kein Remote-Angebot gesetzt → ungültiger Zustand
  await pc.createAnswer();
} catch (err) {
  console.log(err.name);
}
InvalidStateError

Moderne Kurzform mit impliziter Beschreibung

const pc = new RTCPeerConnection();

const handleOffer = async (offer, sendToPeer) => {
  await pc.setRemoteDescription(offer);
  // Erzeugt und setzt die Antwort automatisch (ruft intern createAnswer auf)
  await pc.setLocalDescription();
  sendToPeer(pc.localDescription);
  console.log(pc.localDescription.type);
};
answer

// Wichtig · Fallstricke

  • Reihenfolge beachten: createAnswer() funktioniert nur im Signalisierungszustand have-remote-offer oder have-local-pranswer. Vorher muss setRemoteDescription() mit dem Angebot abgeschlossen sein (await nicht vergessen), sonst gibt es einen InvalidStateError.
  • Tracks vor der Antwort hinzufügen: Medien, die erst nach createAnswer() per addTrack() dazukommen, stehen nicht in der Antwort und lösen eine erneute Aushandlung (negotiationneeded) aus.
  • Antwort wird nicht automatisch gesetzt: Ohne setLocalDescription(answer) startet kein ICE-Gathering und keine Verbindung.
  • SDP nicht manuell verändern („SDP-Munging“): Das ist fehleranfällig und browserabhängig. Codecs lieber mit RTCRtpTransceiver.setCodecPreferences() und Richtungen über transceiver.direction steuern.
  • Sicherheit: Die SDP enthält ICE-Zugangsdaten und unter Umständen lokale IP-Adressen. Den Signalisierungskanal deshalb immer verschlüsselt (WSS/HTTPS) und authentifiziert betreiben. getUserMedia() braucht einen sicheren Kontext.
  • Kompatibilität: Die Promise-Variante wird von allen modernen Browsern unterstützt. Die Callback-Signatur ist veraltet. Die parameterlose Kurzform setLocalDescription() gibt es ab Chrome 80, Firefox 75 und Safari 14.1.