Start · Sprachen · JavaScript · Referenz · new XRMediaBinding()

new XRMediaBinding()

Methode

Erstellt ein <code>XRMediaBinding</code>-Objekt, mit dem sich <code>HTMLVideoElement</code>-Inhalte als WebXR-Komposition-Layer in einer immersiven Sitzung darstellen lassen.

seit JavaScript WebXR Layers API (experimentell) – Chromium-basier Kategorie: webapi

Signatur

new XRMediaBinding(session)

Beschreibung

Der Konstruktor XRMediaBinding() gehört zur WebXR Layers API. Er verknüpft eine laufende, immersive XRSession mit Medienquellen. Über das zurückgegebene Objekt erzeugt man mit createQuadLayer(), createCylinderLayer() und createEquirectLayer() Layer, die ein <video>-Element direkt im Compositor des XR-Geräts anzeigen.

Solche Medien-Layer sind in XR der empfohlene Weg für Videos wie 360°-Filme, virtuelle Kinoleinwände oder Stereo-Clips. Das Video landet nicht in einer WebGL-Textur, die man jeden Frame neu zeichnen muss. Der Compositor tastet es direkt ab. Das Bild ist dadurch deutlich schärfer, hat weniger Latenz und kostet weniger GPU-Leistung.

Voraussetzung ist eine Sitzung, die mit dem Feature "layers" angefordert wurde (requiredFeatures oder optionalFeatures). Die erzeugten Layer werden erst sichtbar, wenn man sie mit session.updateRenderState({ layers: [...] }) in die Layer-Liste der Sitzung einträgt.

Parameter

Name Typ Default Beschreibung
$session Pflicht XRSession Eine aktive, immersive Sitzung ("immersive-vr" oder "immersive-ar"), an die die Medien-Layer gebunden werden. Die Sitzung darf noch nicht beendet sein.

Rückgabewert

Typ
XRMediaBinding
Beschreibung
Ein neues XRMediaBinding-Objekt. Seine Methoden createQuadLayer(), createCylinderLayer() und createEquirectLayer() erzeugen Video-Layer für die übergebene Sitzung.

Beispiele

Sitzung mit Layers-Feature starten und Binding erzeugen

const startXR = async () => {
  if (!navigator.xr || typeof XRMediaBinding === 'undefined') {
    console.log('WebXR-Medien-Layer werden nicht unterstützt');
    return;
  }

  const session = await navigator.xr.requestSession('immersive-vr', {
    requiredFeatures: ['layers']
  });

  const mediaBinding = new XRMediaBinding(session);
  console.log(mediaBinding instanceof XRMediaBinding);
  return { session, mediaBinding };
};

document.querySelector('#enter-vr').addEventListener('click', startXR);
true

Virtuelle Kinoleinwand mit einem Quad-Layer

const video = document.querySelector('#movie');

const playOnScreen = async () => {
  const session = await navigator.xr.requestSession('immersive-vr', {
    requiredFeatures: ['layers']
  });
  const refSpace = await session.requestReferenceSpace('local');
  const mediaBinding = new XRMediaBinding(session);

  // Metadaten laden, damit die Videogröße bekannt ist
  if (video.readyState < HTMLMediaElement.HAVE_METADATA) {
    await new Promise((resolve) =>
      video.addEventListener('loadedmetadata', resolve, { once: true })
    );
  }

  const screen = mediaBinding.createQuadLayer(video, {
    space: refSpace,
    layout: 'mono',
    // 3 m vor dem Nutzer auf Augenhöhe
    transform: new XRRigidTransform({ x: 0, y: 1.6, z: -3 }),
    width: 3.2 // Höhe ergibt sich aus dem Seitenverhältnis
  });

  session.updateRenderState({ layers: [screen] });
  await video.play();
};

document.querySelector('#cinema').addEventListener('click', playOnScreen);

360°-Stereovideo als Equirect-Layer

const show360 = async (videoEl) => {
  const session = await navigator.xr.requestSession('immersive-vr', {
    requiredFeatures: ['layers']
  });
  const refSpace = await session.requestReferenceSpace('local');

  try {
    const binding = new XRMediaBinding(session);
    const sphere = binding.createEquirectLayer(videoEl, {
      space: refSpace,
      layout: 'stereo-top-bottom'
    });
    session.updateRenderState({ layers: [sphere] });
    await videoEl.play();
  } catch (err) {
    // z. B. InvalidStateError, wenn die Sitzung bereits beendet ist
    console.error(`${err.name}: ${err.message}`);
    await session.end();
  }
};

show360(document.querySelector('#pano'));

// Wichtig · Fallstricke

  • Ausnahmen: Der Konstruktor wirft eine InvalidStateError-DOMException, wenn die Sitzung schon beendet ist oder nicht immersiv ist (z. B. \"inline\").
  • Feature \"layers\": Ohne dieses Feature bei requestSession() schlagen die create*Layer()-Aufrufe fehl. Fordert man es nur über optionalFeatures an, sollte man vor der Nutzung prüfen, ob es tatsächlich aktiv ist (session.enabledFeatures).
  • Layer-Reihenfolge: Setzt updateRenderState({ layers }) eine Liste, ersetzt das die bisherigen Layer. Wer zusätzlich WebGL-Inhalte zeigen will, muss den eigenen XRProjectionLayer mit in die Liste aufnehmen. Die Reihenfolge im Array bestimmt, was vorne liegt.
  • Video-Quelle: Videos von fremden Origins brauchen korrekte CORS-Header und das Attribut crossorigin. Die Wiedergabe unterliegt den üblichen Autoplay-Regeln. play() sollte daher aus einer Nutzergeste heraus starten.
  • Kompatibilität: Die API ist experimentell und nur in einigen Chromium-basierten XR-Browsern verfügbar (z. B. Meta Quest Browser). Safari und Firefox unterstützen sie nicht. Prüfe sie vorher mit typeof XRMediaBinding !== 'undefined'. Sie funktioniert nur in sicheren Kontexten (HTTPS).