Start · Sprachen · JavaScript · Referenz · RTCIceCandidate.sdpMLineIndex

RTCIceCandidate.sdpMLineIndex

Eigenschaft

Schreibgeschützter, nullbasierter Index der m-Line im SDP, deren Medienbeschreibung zu diesem ICE-Kandidaten gehört – oder <code>null</code>.

seit JavaScript Baseline: alle modernen Browser (Chrome, Firefox, Kategorie: webapi

Signatur

RTCIceCandidate.sdpMLineIndex

Beschreibung

Die schreibgeschützte Eigenschaft sdpMLineIndex eines RTCIceCandidate gibt an, zu welcher Medienbeschreibung (m-Line, also einer Zeile wie m=audio … oder m=video …) im SDP der Kandidat gehört. Die Zählung beginnt bei 0: Die erste m-Line im Angebot bzw. in der Antwort hat den Index 0, die zweite den Index 1 usw.

Der Wert stammt aus dem Feld sdpMLineIndex des Objekts, mit dem der Kandidat erzeugt wurde (new RTCIceCandidate(init)). Wenn der Browser lokale Kandidaten sammelt, befüllt er den Wert selbst, und das Ereignis icecandidate liefert ihn mit. Beim Signaling überträgt man ihn zusammen mit candidate und sdpMid an die Gegenstelle. Dort ordnet RTCPeerConnection.addIceCandidate() den Kandidaten damit dem richtigen Transceiver zu.

Neben dem Index gibt es die Eigenschaft sdpMid, die Media-Stream-Identifikation (Wert des Attributs a=mid:). Sind beide gesetzt, hat sdpMid Vorrang. sdpMLineIndex wird nur ausgewertet, wenn sdpMid null ist. Mindestens eines der beiden Felder muss gesetzt sein, sonst wirft der Konstruktor bzw. addIceCandidate() einen TypeError.

Rückgabewert

Typ
number | null
Beschreibung
Eine vorzeichenlose 16-Bit-Ganzzahl als nullbasierter Index der zugehörigen m-Line, oder null, wenn beim Erzeugen kein Index angegeben wurde.

Beispiele

Kandidat erzeugen und Index auslesen

const candidate = new RTCIceCandidate({
  candidate: 'candidate:842163049 1 udp 1677729535 203.0.113.5 50000 typ srflx raddr 192.168.1.10 rport 50000',
  sdpMid: '0',
  sdpMLineIndex: 0
});

console.log(candidate.sdpMLineIndex);
console.log(candidate.sdpMid);
0 "0"

Lokale Kandidaten per Signaling versenden

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

pc.addEventListener('icecandidate', ({ candidate }) => {
  if (!candidate) return; // Sammeln abgeschlossen
  console.log(`Kandidat für m-Line ${candidate.sdpMLineIndex} (mid=${candidate.sdpMid})`);
  ws.send(JSON.stringify({
    type: 'candidate',
    candidate: candidate.candidate,
    sdpMid: candidate.sdpMid,
    sdpMLineIndex: candidate.sdpMLineIndex
  }));
});

pc.addTransceiver('audio');
pc.addTransceiver('video');
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
Kandidat für m-Line 0 (mid=0) Kandidat für m-Line 1 (mid=1) ...

Empfangenen Kandidaten robust hinzufügen

const handleRemoteCandidate = async (pc, msg) => {
  // Ältere Gegenstellen senden evtl. nur den Index
  const init = {
    candidate: msg.candidate,
    sdpMid: msg.sdpMid ?? null,
    sdpMLineIndex: msg.sdpMLineIndex ?? null
  };
  if (init.sdpMid === null && init.sdpMLineIndex === null) {
    console.warn('Kandidat ohne sdpMid/sdpMLineIndex verworfen');
    return;
  }
  try {
    await pc.addIceCandidate(init);
  } catch (err) {
    console.error('addIceCandidate fehlgeschlagen:', err);
  }
};

Kandidaten nach Medienspur gruppieren

const byMLine = new Map();

pc.onicecandidate = ({ candidate }) => {
  if (!candidate) {
    for (const [index, list] of byMLine) {
      console.log(`m-Line ${index}: ${list.length} Kandidaten`);
    }
    return;
  }
  const key = candidate.sdpMLineIndex ?? 'unbekannt';
  if (!byMLine.has(key)) byMLine.set(key, []);
  byMLine.get(key).push(candidate.candidate);
};
m-Line 0: 4 Kandidaten m-Line 1: 4 Kandidaten

// Wichtig · Fallstricke

  • Schreibgeschützt: Eine Zuweisung wie candidate.sdpMLineIndex = 1 ändert nichts und wirft im Strict Mode einen Fehler. Den Wert setzt man nur über das Init-Objekt des Konstruktors.
  • sdpMid hat Vorrang: Sind beide Werte gesetzt, gilt sdpMid. Ein widersprüchlicher Index wird dann ignoriert. Sind beide null, wirft der Konstruktor bzw. addIceCandidate() einen TypeError.
  • BUNDLE: Mit a=group:BUNDLE nutzen alle Medien denselben Transport. Viele Kandidaten gehören dann formal nur zur ersten m-Line (Index 0), obwohl sie für alle Spuren gelten.
  • Serialisierung: Mit candidate.toJSON() bzw. JSON.stringify(candidate) werden candidate, sdpMid, sdpMLineIndex und usernameFragment übernommen. Man kann das Ergebnis also direkt übers Signaling senden.
  • Kandidat für das Ende des Sammelns: Ein Kandidat mit leerem candidate-String markiert das Ende der Kandidaten für eine m-Line. Das Ereignis icecandidate mit candidate === null markiert das Ende für die gesamte Verbindung.
  • Kompatibilität: Wird in allen aktuellen Browsern unterstützt. Ältere Implementierungen, etwa Chrome vor dem Unified Plan, konnten beim Signaling ausschließlich auf den Index angewiesen sein.