# Normalize Uploaded Audio for Web and App Playback | AudioDN

> Automatically convert user-uploaded audio into a consistent playback variant for websites, mobile apps, and custom audio players without operating your own transcoding pipeline.

Source: https://audiodeliverynetwork.com/examples/prepare-audio-for-playback/

---

# Standardize Uploaded Audio for Reliable Playback

AudioDN is an audio processing and delivery API. It takes inconsistent, supported source audio — a phone recording, a studio export, a podcast host’s odd codec choice — and produces one predictable, playback-ready variant, then delivers it over signed URLs. Configure the output once (this example uses AAC at 128 kbps) and AudioDN applies that recipe to new uploads automatically. Your application only uploads the source, waits for processing to finish, and requests the variant by name. You do not operate FFmpeg, transcoding queues, or delivery infrastructure.

#### What normalize means here

In this example, **normalize** means _format standardization_: a consistent output codec, bitrate, and channel configuration, plus optional metadata and cover-art stripping, delivered as one named variant. It does **not** mean loudness normalization — AudioDN does not perform LUFS targeting, true-peak limiting, gain adjustment, or dynamic-range processing in this workflow.

## At a glance

<table class="w-full border-collapse border border-border text-sm"><tbody><tr><th class="border border-border bg-muted px-3 py-2 text-left font-medium align-top w-48">Problem</th><td class="border border-border px-3 py-2 text-muted-foreground">Uploaded audio arrives in inconsistent formats, codecs, and qualities.</td></tr><tr><th class="border border-border bg-muted px-3 py-2 text-left font-medium align-top">Input</th><td class="border border-border px-3 py-2 text-muted-foreground">Any AudioDN-supported source audio (for example WAV, FLAC, MP3).</td></tr><tr><th class="border border-border bg-muted px-3 py-2 text-left font-medium align-top">Output</th><td class="border border-border px-3 py-2 text-muted-foreground">One consistently named playback variant — here <code>aac</code> at 128 kbps, delivered as <code>audio/aac</code>.</td></tr><tr><th class="border border-border bg-muted px-3 py-2 text-left font-medium align-top">Configured</th><td class="border border-border px-3 py-2 text-muted-foreground">Once, as an organization-wide variant recipe (or per track via the API).</td></tr><tr><th class="border border-border bg-muted px-3 py-2 text-left font-medium align-top">Your application handles</th><td class="border border-border px-3 py-2 text-muted-foreground">Uploading the source and integrating playback.</td></tr><tr><th class="border border-border bg-muted px-3 py-2 text-left font-medium align-top">AudioDN handles</th><td class="border border-border px-3 py-2 text-muted-foreground">Processing, transcoding, storage, and secure delivery.</td></tr></tbody></table>

## How the workflow fits together

A supported upload becomes a consistent, playable file in four managed steps. Processing must complete before playback, so your application waits for the track to become `ready` and then requests the variant by name.

High-level flow

```
Supported source audio (WAV, FLAC, MP3, ...)
        |
        v
Upload to AudioDN
        |
        v
AudioDN processes the track      (track_status_id: processing)
        |
        v
Configured variant generated     (track_status_id: ready)
        |
        v
Play the same named variant on web, mobile, or server
```

## 1\. Configure the output first

The transcode **variant** is the feature this example is really about. A variant is a reusable recipe that tells AudioDN how to turn any supported upload into a specific output. Configure it once and AudioDN generates that same named variant for new uploads automatically — your code never has to detect or special-case the source codec, and it always requests the result by the same name.

### Configure an aac transcode variant in the dashboard

1.  Log in to the [AudioDN dashboard](https://account.audiodeliverynetwork.com) and open **Variants**.
    
2.  Click **Add Variant** and choose the **Transcode** type.
3.  Set the index to `aac`, codec to **AAC**, and bitrate to **128**. Leave stereo on, and enable strip tags and strip cover art to standardize metadata.
    
4.  Save. New uploads are transcoded to this `aac` variant automatically.

#### Adding the variant to an existing track

Organization-wide recipes apply to new uploads. To add the same output to a single track that is already `ready`, append a track-specific variant with `POST /v1/track/:track_id/variant` (codec and bitrate default to `aac` at `128`). Full field reference: [Variants API](/docs/api/variants).

### Why AAC at 128 kbps

AAC is a practical default for general web and app playback: it is broadly supported across modern browsers, mobile operating systems, and media players, and 128 kbps strikes a useful balance of quality, file size, and streaming performance for typical listening. AudioDN delivers this variant with the content type `audio/aac`. If your product needs different trade-offs, configure a different codec or bitrate, or add more variants — see [Variant Types](/docs/variant-types).

## 2\. Upload the source

It does not matter how the file arrives — a lossless studio master, a compressed voice memo, or whatever a listener’s phone produced. The upload is a short, explicit sequence: create a session (optionally with a nested track to create the first track up front), create any additional tracks, PUT the bytes to the track’s upload URL, then wait until the track is `ready`.

Upload sequence (conceptual)

```
POST /v1/upload_session                       -> upload_session_id
  (optional nested track object)               -> also track_id + track_upload.upload_url
POST /v1/upload/{upload_session_id}/track     -> track_upload.upload_url  (per additional file)
PUT  {track_upload.upload_url}                  (send the source bytes)
GET  /v1/track/{track_id}                       (poll until track_status_id = ready)
Request the configured variant                 (e.g. variants="aac")
```

#### Optional nested track

By default an upload session returns an `upload_session_id` only. Include a nested `track` object on `POST /v1/upload_session` to also receive `track_upload.upload_url` in that response (you can still add more tracks later). Otherwise create each track with `POST /v1/upload/{upload_session_id}/track`.

Then poll `GET /v1/track/:track_id` until `track_status_id` is `ready`, or listen for a track webhook, before starting playback.

Full upload example (API and Uploader component)ShowHide

### Option A — Upload via the API

Your server (or client, with a Client-Side Upload key) drives the upload directly.

Create an upload session

#### Example Request

  

```
# COLLECTION_ID: uuid of the collection to upload into
curl -X POST "https://api.audiodelivery.net/v1/upload_session" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "collection_id": "COLLECTION_ID",
  "expires_in": 7200
}'
```

```
// COLLECTION_ID: uuid of the collection to upload into

const payload = {
  "collection_id": "COLLECTION_ID",
  "expires_in": 7200
};

const response = await fetch('https://api.audiodelivery.net/v1/upload_session', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(payload)
});

const data = await response.json();
```

```
# COLLECTION_ID: uuid of the collection to upload into

import requests

headers = {
    "Authorization": "Bearer YOUR_API_KEY",
    "Content-Type": "application/json",
}

payload = {
    "collection_id": "COLLECTION_ID",
    "expires_in": 7200
}

response = requests.post(
    "https://api.audiodelivery.net/v1/upload_session",
    headers=headers,
    json=payload,
)
data = response.json()
```

Create a track in the session

#### Example Request

  

```
# SESSION_ID: upload_session_id returned by the previous call
curl -X POST "https://api.audiodelivery.net/v1/upload/SESSION_ID/track" \
  -H "Content-Type: application/json" \
  -d '{
  "file_name": "track.wav"
}'
```

```
// SESSION_ID: upload_session_id returned by the previous call

const payload = {
  "file_name": "track.wav"
};

const response = await fetch('https://api.audiodelivery.net/v1/upload/SESSION_ID/track', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(payload)
});

const data = await response.json();
```

```
# SESSION_ID: upload_session_id returned by the previous call

import requests

headers = {
    "Content-Type": "application/json",
}

payload = {
    "file_name": "track.wav"
}

response = requests.post(
    "https://api.audiodelivery.net/v1/upload/SESSION_ID/track",
    headers=headers,
    json=payload,
)
data = response.json()
```

Upload the file bytes

PUT track\_upload.upload\_url

```
# After create-track returns track_upload.upload_url, PUT the source bytes.
# Any supported source format works, regardless of its original quality or codec.
curl -X PUT "$UPLOAD_URL" \
  --data-binary @track.wav \
  -H "Content-Type: audio/wav"
```

### Option B — Upload via the Uploader component

Drop a drag-and-drop uploader into your page; no backend required with a Client-Side Upload key.

#### Dependency

 

```
npm install @audiodn/components
```

```
<script type="module" src="https://unpkg.com/@audiodn/components@latest/dist/uploader.js"></script>
```

#### Usage

```
<script type="module">
import '@audiodn/components/uploader';
</script>

<audiodn-uploader
api-key="YOUR_UPLOAD_API_KEY"
collection-id="COLLECTION_ID"
></audiodn-uploader>
```

The component handles drag-and-drop, per-file progress, and retries for you. Full attribute reference: [Uploader component docs](/docs/components/uploader).

Complete field-by-field reference: [Upload Sessions API](/docs/api/upload-sessions).

## 3\. Play the variant

Once the track is `ready`, every surface your product ships to requests the exact same variant by name and gets the exact same predictable file — no format detection, no per-platform special-casing. The fastest path on the web is the `<audiodn-player>` component with a Client-Side Player key:

#### Dependency

 

```
npm install @audiodn/components
```

```
<script type="module" src="https://unpkg.com/@audiodn/components@latest/dist/player.js"></script>
```

#### Usage

```
<script type="module">
  import '@audiodn/components/player';
</script>

<audiodn-player
  api-key="YOUR_PLAYER_API_KEY"
  scope="track"
  id="TRACK_ID"
  variants="aac"
  size="regular"
></audiodn-player>
```

### Live demo

The homepage hero track, played here from its single standardized `aac` variant.

Music by [Nyktrn](https://soundcloud.com/nyktrn)

### Request the same variant anywhere

The player is optional. Custom web, mobile, Flutter, native, and server applications can create a play session and stream the returned signed URL for the same named variant, or sign delivery URLs directly for backend playback.

-   **Website / custom player** — embed `<audiodn-player>`, or request the file for your own UI. See the [Web Integration](/docs/integration/web) guide.
    
-   **Mobile app** — create a play session requesting the `aac` variant from Swift, Kotlin, or Flutter, then stream the signed URL with any platform audio player. See [Mobile Integration](/docs/integration/mobile).
    
-   **Server / API** — sign delivery URLs for backend-to-backend playback or downloads. See [Signed Delivery](/docs/integration/signed-delivery) and the [Variants API](/docs/api/variants).
    

More player options (themes, sizes, playlists, cover art): [Player component docs](/docs/components/player).

## When to use this workflow

Reach for this whenever your product accepts audio you do not control and needs it to play back consistently. That covers uploads from users, artists, phones, browsers, recording devices, editing software, external systems, and multiple production tools at once.

It fits music platforms, podcasts, voice recordings, social audio, educational products, marketplaces, AI-generated audio apps, and other user-generated audio products. In each case AudioDN can replace the custom infrastructure you would otherwise operate: upload storage, processing queues, FFmpeg workers, output storage, delivery signing, and playback delivery.

## What this example does not cover

This example focuses on producing one consistent playback format from inconsistent uploads. The following are related but separate capabilities, not part of this workflow:

-   **Preview clips** — short, seek-restricted excerpts. See [Preview clip player](/examples/preview-clip-player).
-   **Waveforms** — waveform image or video variants. See [Variant Types](/docs/variant-types).
-   **Additional variants** — extra bitrates or codecs alongside `aac` for multi-quality delivery.
-   **Lossless downloads** — offering FLAC or WAV downloads from the same upload.
-   **Loudness normalization** — AudioDN does not perform LUFS targeting or gain adjustment; this workflow standardizes format, not loudness.

## FAQ

### How do I normalize user-uploaded audio for web playback?

Upload the source to AudioDN, wait until the track's track\_status\_id is ready, then request your configured transcode variant (for example AAC at 128 kbps). AudioDN standardizes the codec, bitrate, and channel layout so every upload plays back as the same predictable file.

### Can AudioDN convert different audio formats into one consistent format?

Yes. AudioDN accepts supported source formats such as WAV, FLAC, and MP3 and transcodes them into a single configured output variant, so your player always requests one consistent file regardless of what was uploaded.

### Do I need to operate FFmpeg?

No. AudioDN runs the transcoding pipeline for you. You upload the source and request the finished variant; you do not run FFmpeg workers, processing queues, or output storage yourself.

### Does AudioDN normalize audio loudness?

No. This workflow performs format standardization (codec, bitrate, channel configuration, and metadata handling), not loudness normalization, LUFS targeting, true-peak limiting, or gain adjustment.

### When is the playback variant available?

After processing completes. Poll GET /v1/track/{track\_id} until track\_status\_id is ready, or listen for a track webhook. Begin playback only once the track is ready.

### Can I use my own audio player?

Yes. The audiodn-player web component is optional. Any web, mobile, or server client can create a play session and stream the returned signed URL for the same named variant.

### Can the same variant be used in a mobile app?

Yes. Native iOS, Android, and Flutter apps request the same variant by name through a play session and play the returned signed URL with the platform audio player.

### Does creating an upload session return the upload URL?

By default, no — creating an upload session returns an upload\_session\_id only. Optionally include a nested track object on POST /v1/upload\_session to also receive track\_upload.upload\_url on that response (you can still add more tracks later). Otherwise create a track with POST /v1/upload/{upload\_session\_id}/track; that response contains the track-specific upload URL.

## Checklist

-   An `aac` transcode variant recipe exists at 128 kbps (configured once in the dashboard, or added to a single track via `POST /v1/track/:track_id/variant`).
-   A supported source file uploaded — via the API or the `<audiodn-uploader>` component — and reached `track_status_id` `ready`.
-   Player is scoped to the track, requesting the `aac` variant with a Client-Side Player key.
-   The same `aac` variant is requested consistently across web, mobile, and server integrations.

Published July 15, 2026
