Launch-Aktion: Die Pläne Creator und Business sind für begrenzte Zeit rabattiert. Preise ansehen

Track-Processing-Webhook

Der Track-Processing-Webhook ermöglicht es Ihrer Anwendung, ohne Polling auf das Ergebnis eines Tracks zu reagieren. AudioDN sendet eine HTTP-POST-Anfrage an die für Ihre Organisation konfigurierte Webhook-URL, wenn ein Track einen terminalen Status erreicht oder wenn sein vollständiger Dateisatz abgeschlossen ist. Für Fortschritt auf Dateiebene, während jede Variante erzeugt wird, nutzen Sie stattdessen den Track-File-Webhook.

Im Dashboard konfiguriert

Die Webhook-URL wird in Ihrem Settings → Webhook-Bereich im Dashboard festgelegt, nicht über die API. Lassen Sie das Feld leer, um Webhooks zu deaktivieren. Für Ereignisse auf Dateiebene siehe den Track-File-Webhook, und für Erstellen/Aktualisieren/Löschen-Ereignisse von Sammlungen siehe den Collection-Sync-Webhook.

Wann er ausgelöst wird

Um unnötiges Rauschen zu vermeiden, gibt dieser Webhook keine Übergangsstatus weiter (processing, fallback, fallback_processing) und auch nicht den anfänglichen Status initialized. Er wird nur bei relevanten Ereignissen zugestellt:

  • Terminaler Status — der Track erreicht ready, incomplete, error oder init_error.
  • Dateien abgeschlossentrack.files_completed_at wird gesetzt, sobald jede Variante (einschließlich optionaler und nachträglich hinzugefügter) versucht wurde. Dies kann nach einem früheren ready eintreten, sodass derselbe Track zweimal zugestellt werden kann: einmal, wenn er abspielbar wird, und einmal, wenn der vollständige Dateisatz fertig ist.

Ein typischer Track wird einmal zugestellt (der Status wird zu ready, und die Dateien sind im selben Schritt abgeschlossen) oder zweimal (frühes ready durch erforderliche Varianten, dann ein späteres Ereignis „Dateien abgeschlossen“, sobald optionale Varianten fertig sind).

  • Wird als HTTP-POST mit Content-Type: application/json gesendet.
  • Enthält einen X-ADN-Event: track.status_changed-Header.
  • Die Zustellung erfolgt nach dem Prinzip „fire-and-forget“ / mindestens einmal — gestalten Sie Ihren Handler idempotent.
  • Die Reihenfolge der Ereignisse ist nicht garantiert; verlassen Sie sich auf die Felder status, previous_status und track.files_completed_at statt auf die Ankunftsreihenfolge.
  • Anfragen sind derzeit unsigniert. Behandeln Sie die Webhook-URL als Geheimnis und prüfen Sie bei Bedarf die track_id gegen die API.
  • Antworten Sie zeitnah mit einem 2xx-Statuscode, um den Empfang zu bestätigen.

Track-Statuswerte

Das Feld status spiegelt die track_status_id des Tracks zum Zeitpunkt des Ereignisses wider. Die möglichen Werte sind:

StatusTerminalBedeutung
initializedNeinDer Track-Datensatz wurde erstellt und wartet darauf, dass der Upload seiner Datei abgeschlossen wird. Dies ist das erste Ereignis, das Sie erhalten.
processingNeinDer Upload wurde abgeschlossen, und AudioDN transcodiert, erzeugt Wellenformen, extrahiert Metadaten und baut Varianten auf.
fallbackNeinDer primäre Prozessor konnte die Datei nicht verarbeiten, daher wurde sie für den Fallback-Prozessor in die Warteschlange gestellt.
fallback_processingNeinDer Fallback-Prozessor bearbeitet den Track aktiv.
readyJaDie Verarbeitung wurde erfolgreich abgeschlossen. Alle Track-Dateien sind verfügbar, und der Track ist zur Wiedergabe bereit.
incompleteJaDie Verarbeitung wurde mit einem abspielbaren Track abgeschlossen, aber eine oder mehrere nicht essenzielle Varianten sind fehlgeschlagen. Der Track ist nutzbar.
errorJaDie Verarbeitung ist fehlgeschlagen, und es konnte kein abspielbarer Track erzeugt werden.
init_errorJaDer Track konnte nicht initialisiert werden (zum Beispiel war der Upload ungültig oder nicht lesbar). Es fand keine Verarbeitung statt.

Terminale Status (ready, incomplete, error, init_error) sind Endzustände — ein Track wechselt seinen Status nicht mehr, sobald er einen davon erreicht hat. Die übrigen Status sind Übergangszustände.

Payload-Schema

Jedes Ereignis liefert die gleiche Umschlagstruktur. Da Zustellungen auf terminale Ergebnisse und das Ereignis „Dateien abgeschlossen“ beschränkt sind, ist das files-Array normalerweise befüllt. track.files_completed_at ist bei einem frühen ready null (optionale Varianten laufen noch) und ein Zeitstempel, sobald der vollständige Satz fertig ist. Jede Datei enthält is_success und ein verschachteltes variant-Objekt (Rezept); eine fehlgeschlagene Variante erscheint mit is_success: false, ohne url, und mit dem Grund in status_text.

{
"event": "track.status_changed",
"status": "ready | incomplete | error | init_error",
"previous_status": "string | null",
"organization_id": "uuid",
"creator_id": "uuid | null",
"collection_id": "uuid",
"track_id": "uuid",
"upload_session_id": "uuid | null",
"track": {
  "id": "uuid",
  "track_status_id": "string",
  "upload_session_id": "uuid | null",
  "index": "string",
  "organization_index": "string | null",
  "file_name": "string | null",
  "file_name_original": "string | null",
  "player_title": "string | null",
  "player_subtitle": "string | null",
  "player_color": "string | null",
  "player_color_light": "string | null",
  "player_color_dark": "string | null",
  "order": "number",
  "format": "object | null",
  "metadata": "object | null",
  "duration": "number | null",
  "size": "number | null",
  "files_completed_at": "string | null",
  "cloudflare_image_id": "uuid | null",
  "cover_image": {
    "icon": { "type": "icon", "width": 80, "height": 80, "url": "string" },
    "small": { "type": "small", "width": 200, "height": 200, "url": "string" },
    "regular": { "type": "regular", "width": 400, "height": 400, "url": "string" },
    "large": { "type": "large", "width": 800, "height": 800, "url": "string" }
  },
  "theme": "array | null"
},
"files": [
  {
    "id": "uuid",
    "path": "string",
    "url": "string | null",
    "size": "number | null",
    "content_type": "string | null",
    "file_name": "string",
    "is_public": "boolean",
    "is_success": "boolean",
    "status_text": "string | null",
    "data": "object | null",
    "props": "object | null",
    "variant": {
      "id": "uuid",
      "index": "string",
      "variant_type": {
        "id": "string",
        "viewer_id": "string",
        "title": "string"
      }
    }
  }
]
}

Coverbilder

Wenn ein Track Cover-Artwork besitzt, liefert track.cover_image gebrauchsfertige URLs für jede verfügbare Größe, und track.cloudflare_image_id speichert die zugrunde liegende Bild-ID, falls Sie später eine URL neu aufbauen müssen. Beide sind null, bis ein Cover verfügbar ist (Cover werden während der Verarbeitung extrahiert, sodass frühe Ereignisse wie initialized möglicherweise noch keines enthalten).

Bevorzugen Sie die vorgefertigten cover_image-URLs. Wenn Sie nur die Bild-ID aus einem vorherigen Ereignis haben, können Sie jede Größe selbst konstruieren. Jede URL folgt dem unten stehenden Muster, wobei <variant> eine der benannten Größen ist:

https://imagedelivery.net/iVHDyjXAr_lt5UUJaLbk1Q/{cloudflare_image_id}/{variant}
VarianteAbmessungenBeispiel-URL
icon80 x 80…/{cloudflare_image_id}/icon
small200 x 200…/{cloudflare_image_id}/small
regular400 x 400…/{cloudflare_image_id}/regular
large800 x 800…/{cloudflare_image_id}/large

Dasselbe Schema gilt für das Cover-Artwork von Sammlungen, das vom Collection-Sync-Webhook geliefert wird.

Wenn ein Cover verarbeitet wird, extrahiert ADN daraus auch eine Farbpalette, geliefert als track.theme — ein Array von Farbobjekten mit den Werten hex, area, lightness und saturation (null, bis ein Cover verarbeitet wurde). Dies ist dasselbe theme-Feld, das von der Tracks-API zurückgegeben wird.

Beispiel-Payloads

Frühes „ready“ (erforderliche Varianten abgeschlossen)

Wird gesendet, sobald die erforderlichen Varianten erfolgreich sind und der Track abspielbar ist, während optionale Varianten noch verarbeitet werden. files_completed_at ist null, weil der vollständige Dateisatz noch nicht fertig ist. Ein Track ohne optionale Varianten springt direkt zum unten stehenden abgeschlossenen Ereignis und sendet dieses nie.

{
"event": "track.status_changed",
"status": "ready",
"previous_status": "processing",
"organization_id": "11111111-1111-1111-1111-111111111111",
"creator_id": null,
"collection_id": "22222222-2222-2222-2222-222222222222",
"track_id": "33333333-3333-3333-3333-333333333333",
"upload_session_id": "44444444-4444-4444-4444-444444444444",
"track": {
  "id": "33333333-3333-3333-3333-333333333333",
  "track_status_id": "ready",
  "upload_session_id": "44444444-4444-4444-4444-444444444444",
  "index": "track-index-001",
  "organization_index": "your-track-id-001",
  "file_name": "interview.mp3",
  "file_name_original": "Interview Final.mp3",
  "player_title": "Episode 12",
  "player_subtitle": "The Interview",
  "player_color": "#1DB954",
  "player_color_light": "#1BAA4D",
  "player_color_dark": "#1DB954",
  "order": 0,
  "format": { "codec": "aac", "channels": 2, "sample_rate": 44100 },
  "metadata": null,
  "duration": 1832.5,
  "size": 18234123,
  "files_completed_at": null
},
"files": [ { "..." : "playable transcode file(s) so far" } ]
}

„ready“ und Dateien abgeschlossen (endgültig)

Wird gesendet, sobald jede Variante (erforderlich und optional) versucht wurde. files_completed_at wird gesetzt, und der vollständige Dateisatz liegt vor. Für einen Track ohne optionale Varianten ist dies die einzige Zustellung, die Sie erhalten.

{
"event": "track.status_changed",
"status": "ready",
"previous_status": "processing",
"organization_id": "11111111-1111-1111-1111-111111111111",
"creator_id": null,
"collection_id": "22222222-2222-2222-2222-222222222222",
"track_id": "33333333-3333-3333-3333-333333333333",
"upload_session_id": "44444444-4444-4444-4444-444444444444",
"track": {
  "id": "33333333-3333-3333-3333-333333333333",
  "track_status_id": "ready",
  "upload_session_id": "44444444-4444-4444-4444-444444444444",
  "index": "track-index-001",
  "organization_index": "your-track-id-001",
  "file_name": "interview.mp3",
  "file_name_original": "Interview Final.mp3",
  "player_title": "Episode 12",
  "player_subtitle": "The Interview",
  "player_color": "#1DB954",
  "player_color_light": "#1BAA4D",
  "player_color_dark": "#1DB954",
  "order": 0,
  "format": { "codec": "aac", "channels": 2, "sample_rate": 44100 },
  "metadata": { "artist": "Acme Media" },
  "duration": 1832.5,
  "size": 18234123,
  "files_completed_at": "2026-01-01T12:00:05.000Z",
  "cloudflare_image_id": "77777777-7777-7777-7777-777777777777",
  "cover_image": {
    "icon": { "type": "icon", "width": 80, "height": 80, "url": "https://imagedelivery.net/iVHDyjXAr_lt5UUJaLbk1Q/77777777-7777-7777-7777-777777777777/icon" },
    "small": { "type": "small", "width": 200, "height": 200, "url": "https://imagedelivery.net/iVHDyjXAr_lt5UUJaLbk1Q/77777777-7777-7777-7777-777777777777/small" },
    "regular": { "type": "regular", "width": 400, "height": 400, "url": "https://imagedelivery.net/iVHDyjXAr_lt5UUJaLbk1Q/77777777-7777-7777-7777-777777777777/regular" },
    "large": { "type": "large", "width": 800, "height": 800, "url": "https://imagedelivery.net/iVHDyjXAr_lt5UUJaLbk1Q/77777777-7777-7777-7777-777777777777/large" }
  },
  "theme": [
    { "hex": "#1DB954", "area": 0.42, "lightness": 0.45, "saturation": 0.73 },
    { "hex": "#0E1320", "area": 0.31, "lightness": 0.08, "saturation": 0.35 }
  ]
},
"files": [
  {
    "id": "55555555-5555-5555-5555-555555555555",
    "path": "org/collection/track/transcode.aac",
    "url": "https://cdn.audiodn.com/org/collection/track/transcode.aac",
    "size": 17012344,
    "content_type": "audio/aac",
    "file_name": "transcode.aac",
    "is_public": true,
    "is_success": true,
    "status_text": "OK",
    "data": null,
    "props": null,
    "variant": {
      "id": "66666666-6666-6666-6666-666666666666",
      "index": "transcode-default",
      "variant_type": {
        "id": "transcode",
        "viewer_id": "audio",
        "title": "Transcoded Audio"
      }
    }
  }
]
}

„incomplete“ (teilweiser Erfolg)

Wird gesendet, wenn ein abspielbarer Track erzeugt wurde, aber eine nicht essenzielle Variante fehlgeschlagen ist. Der Track ist weiterhin nutzbar.

{
"event": "track.status_changed",
"status": "incomplete",
"previous_status": "processing",
"organization_id": "11111111-1111-1111-1111-111111111111",
"creator_id": null,
"collection_id": "22222222-2222-2222-2222-222222222222",
"track_id": "33333333-3333-3333-3333-333333333333",
"upload_session_id": "44444444-4444-4444-4444-444444444444",
"track": {
  "id": "33333333-3333-3333-3333-333333333333",
  "track_status_id": "incomplete",
  "upload_session_id": "44444444-4444-4444-4444-444444444444",
  "index": "track-index-001",
  "organization_index": "your-track-id-001",
  "file_name": "interview.mp3",
  "file_name_original": "Interview Final.mp3",
  "player_title": "Episode 12",
  "player_subtitle": "The Interview",
  "player_color": "#1DB954",
  "player_color_light": "#1BAA4D",
  "player_color_dark": "#1DB954",
  "order": 0,
  "format": { "codec": "aac", "channels": 2, "sample_rate": 44100 },
  "metadata": null,
  "duration": 1832.5,
  "size": 18234123,
  "files_completed_at": "2026-01-01T12:00:05.000Z"
},
"files": [
  {
    "id": "55555555-5555-5555-5555-555555555555",
    "path": "org/collection/track/transcode.aac",
    "url": "https://cdn.audiodn.com/org/collection/track/transcode.aac",
    "size": 17012344,
    "content_type": "audio/aac",
    "file_name": "transcode.aac",
    "is_public": true,
    "is_success": true,
    "status_text": "OK",
    "data": null,
    "props": null,
    "variant": {
      "id": "66666666-6666-6666-6666-666666666666",
      "index": "transcode-default",
      "variant_type": {
        "id": "transcode",
        "viewer_id": "audio",
        "title": "Transcoded Audio"
      }
    }
  },
  {
    "id": "99999999-9999-9999-9999-999999999999",
    "path": "org/collection/track/lossless.flac",
    "url": null,
    "size": null,
    "content_type": "audio/flac",
    "file_name": "lossless.flac",
    "is_public": false,
    "is_success": false,
    "status_text": "Source is lossy; cannot produce a lossless output",
    "data": null,
    "props": null,
    "variant": {
      "id": "88888888-8888-8888-8888-888888888888",
      "index": "lossless-download",
      "variant_type": {
        "id": "transcode",
        "viewer_id": "audio",
        "title": "Transcoded Audio"
      }
    }
  }
]
}

„error“ (Fehlschlag)

Wird gesendet, wenn die Verarbeitung fehlschlägt und kein abspielbarer Track erzeugt werden konnte. Das files-Array ist leer.

{
"event": "track.status_changed",
"status": "error",
"previous_status": "processing",
"organization_id": "11111111-1111-1111-1111-111111111111",
"creator_id": null,
"collection_id": "22222222-2222-2222-2222-222222222222",
"track_id": "33333333-3333-3333-3333-333333333333",
"upload_session_id": "44444444-4444-4444-4444-444444444444",
"track": {
  "id": "33333333-3333-3333-3333-333333333333",
  "track_status_id": "error",
  "upload_session_id": "44444444-4444-4444-4444-444444444444",
  "index": "track-index-001",
  "organization_index": "your-track-id-001",
  "file_name": "interview.mp3",
  "file_name_original": "Interview Final.mp3",
  "player_title": "Episode 12",
  "player_subtitle": "The Interview",
  "player_color": "#1DB954",
  "player_color_light": "#1BAA4D",
  "player_color_dark": "#1DB954",
  "order": 0,
  "format": null,
  "metadata": null,
  "duration": null,
  "size": 18234123,
  "files_completed_at": "2026-01-01T12:00:05.000Z"
},
"files": []
}

Zustellung überprüfen

Jeder Zustellversuch wird auf Seiten von AudioDN protokolliert, einschließlich des von Ihrem Endpunkt zurückgegebenen HTTP-Statuscodes. Wenn Sie keine Ereignisse mehr erhalten, prüfen Sie, ob Ihr Endpunkt zügig eine 2xx-Antwort zurückgibt und ob die Webhook-URL in den Settings korrekt ist.

Webhooks verarbeiten

Ein minimaler Handler liest das Feld status und reagiert auf terminale Zustände. Da die Zustellung mindestens einmal und ungeordnet erfolgt, sollten Sie Ihre Logik auf track_id + status stützen statt auf die Empfangsreihenfolge.

app.post('/webhooks/audiodn', (req, res) => {
// Acknowledge quickly, then process asynchronously.
res.sendStatus(200)

const { event, status, track_id } = req.body
if (event !== 'track.status_changed') return

switch (status) {
  case 'ready':
    // Track is playable. track.files_completed_at === null means optional
    // variants are still running (a second delivery will follow once done).
    markTrackReady(track_id, req.body.files)
    break
  case 'incomplete':
    // Playable, but some variants failed. Inspect files[].is_success.
    markTrackReady(track_id, req.body.files)
    flagForReview(track_id)
    break
  case 'error':
  case 'init_error':
    // Processing failed; no playable track was produced.
    markTrackFailed(track_id)
    break
}
// Note: transitional statuses (processing / fallback*) are not delivered.
// For per-file progress, use the Track File webhook instead.
})