Start · Sprachen · JavaScript · Referenz · USBIsochronousOutTransferPacket

USBIsochronousOutTransferPacket

Schnittstelle

Beschreibt das Ergebnis eines einzelnen Pakets einer isochronen OUT-Übertragung, die mit <code>USBDevice.isochronousTransferOut()</code> gestartet wurde.

seit JavaScript Chrome/Edge 61+ (experimentell, nur Chromium-Brows Kategorie: webapi

Signatur

interface USBIsochronousOutTransferPacket

Beschreibung

Das Interface USBIsochronousOutTransferPacket gehört zur WebUSB API. Bei einer isochronen Übertragung werden Daten in feste Zeitfenster aufgeteilt, zum Beispiel für Audio- oder Videostreams an ein USB-Gerät. Ruft man USBDevice.isochronousTransferOut(endpointNumber, data, packetLengths) auf, wird der Puffer data anhand der Längen in packetLengths in einzelne Pakete zerlegt. Für jedes Paket liefert das USBIsochronousOutTransferResult in seinem Array packets ein eigenes USBIsochronousOutTransferPacket.

Jedes Paket-Objekt hat zwei schreibgeschützte Eigenschaften:

  • bytesWritten (number): die Anzahl der Bytes, die in diesem Paket tatsächlich an das Gerät gesendet wurden.
  • status (string): der Status des Pakets, entweder "ok" (erfolgreich) oder "stall" (der Endpunkt hat einen Stall gemeldet).

Im Gegensatz zu Bulk- oder Interrupt-Übertragungen gibt es bei isochronen Übertragungen keine automatische Wiederholung. Deshalb sollte man jedes Paket einzeln prüfen: Einzelne Pakete können fehlschlagen oder unvollständig sein, obwohl das Promise erfolgreich erfüllt wird. Den Konstruktor braucht man in der Praxis vor allem, um Ergebnisse in Tests oder Polyfills nachzubilden.

Parameter

Name Typ Default Beschreibung
$status Pflicht "ok" | "stall" Nur beim Konstruktor: Status des Pakets. Wird als Eigenschaft status übernommen.
$bytesWritten number 0 Nur beim Konstruktor: Anzahl der gesendeten Bytes. Wird als Eigenschaft bytesWritten übernommen.

Rückgabewert

Typ
USBIsochronousOutTransferPacket
Beschreibung
Ein Objekt mit den schreibgeschützten Eigenschaften bytesWritten und status. Der Browser erzeugt es normalerweise selbst als Element von USBIsochronousOutTransferResult.packets.

Beispiele

Paket-Objekt direkt erzeugen (z. B. für Tests)

// Ergebnis eines Pakets nachbilden, etwa für einen Mock von USBDevice
const packet = new USBIsochronousOutTransferPacket('ok', 192);
console.log(packet.status, packet.bytesWritten);

const stalled = new USBIsochronousOutTransferPacket('stall');
console.log(stalled.status, stalled.bytesWritten);
ok 192 stall 0

Audio-Frames isochron senden und jedes Paket prüfen

const sendAudioFrames = async (device, endpointNumber, samples) => {
  const packetSize = 192; // z. B. 48 kHz, 16 Bit, Stereo, 1 ms
  const packetCount = Math.ceil(samples.byteLength / packetSize);
  const packetLengths = Array.from({ length: packetCount }, (_, i) =>
    Math.min(packetSize, samples.byteLength - i * packetSize)
  );

  const result = await device.isochronousTransferOut(
    endpointNumber,
    samples,
    packetLengths
  );

  result.packets.forEach((packet, i) => {
    if (packet.status !== 'ok') {
      console.warn(`Paket ${i}: Status ${packet.status}`);
    } else if (packet.bytesWritten < packetLengths[i]) {
      console.warn(`Paket ${i}: nur ${packet.bytesWritten}/${packetLengths[i]} Bytes`);
    }
  });

  return result.packets.reduce((sum, p) => sum + p.bytesWritten, 0);
};

// Nutzung (nach navigator.usb.requestDevice() und device.open()):
// const total = await sendAudioFrames(device, 1, new Uint8Array(1920));
// console.log(`Gesendet: ${total} Bytes`);
Gesendet: 1920 Bytes

Statistik über erfolgreiche und fehlerhafte Pakete

const summarize = (packets) => {
  const ok = packets.filter((p) => p.status === 'ok').length;
  const stalls = packets.length - ok;
  const bytes = packets.reduce((sum, p) => sum + p.bytesWritten, 0);
  return { ok, stalls, bytes };
};

const packets = [
  new USBIsochronousOutTransferPacket('ok', 64),
  new USBIsochronousOutTransferPacket('ok', 64),
  new USBIsochronousOutTransferPacket('stall', 0)
];
console.log(summarize(packets));
{ ok: 2, stalls: 1, bytes: 128 }

// Wichtig · Fallstricke

Browser-Kompatibilität: WebUSB gibt es nur in Chromium-Browsern (Chrome, Edge, Opera) auf dem Desktop und unter Android. Firefox und Safari unterstützen die API nicht. Die API ist nur in sicheren Kontexten (HTTPS) verfügbar und kann per Permissions-Policy usb gesperrt sein. Prüfe die Verfügbarkeit vorher mit 'usb' in navigator.

Fallstricke:

  • Das Promise von isochronousTransferOut() wird auch dann erfüllt, wenn einzelne Pakete "stall" melden. Werte darum immer jedes Paket in packets aus.
  • Isochrone Übertragungen wiederholen verlorene Daten nicht. Bei Echtzeit-Streams musst du fehlende Pakete gegebenenfalls selbst ausgleichen.
  • Die Summe von packetLengths muss zur Größe des Datenpuffers passen. Außerdem muss das Interface mit dem isochronen Endpunkt vorher mit claimInterface() reserviert und die passende Alternate Setting mit selectAlternateInterface() gewählt worden sein.
  • Viele Geräteklassen (z. B. USB-Audio) werden vom Betriebssystem beansprucht und sind über WebUSB nicht erreichbar.