---
title: Audio detach
description: Extract the audio track of one Sume-hosted video into a durable wav or mp3. The video is untouched.
---

> **Current SoT.** Media L2 demux (`sume/audio-detach-1.0`, #5953). Dest
> and prod. This is **not** clip inspection — that is
> [video inspect](/models/video-inspect). For many ranges, detach **once**
> then split with [timeline audio](/models/timeline-audio).

Audio detach 1.0 takes **one** workspace `media.sume.com` video and
returns a **new** audio artifact. Default is sample-exact wav
(`pcm_s16le`) — what `timeline_create` `audio.url`,
`POST /v1/timeline-1.0/audio`, and speech-to-text want. The video is
untouched. The server compiles ffmpeg on the worker media runtime
(`apps/api/src/routes.ts` `createAudioDetachV1` /
`submitSumeAudioDetachJob`).

```text
POST /v1/audio-detach
POST /v1/models/sume/audio-detach-1.0/runs   # same body, no extra `model` field
```

There is **no** `GET /v1/audio-detach/:id`. Poll the job envelope:

```text
GET /v1/jobs/:id/status
GET /v1/jobs/:id/result
```

Hosted MCP: `audio_detach` (`packages/mcp-server/src/mcp.ts`). Writes
need `idempotency_key` (and `mcp:write` under OAuth). Flow:
`audio_detach` → `jobs_wait` → `jobs_result`.

## Create a detach

Required: `video_url` (this workspace’s `media.sume.com` artifact or
asset). There is no open-internet fetch — import first
(`POST /v1/media-imports`). `Idempotency-Key` is required.

Optional: `format`, `range`, `channels`, `sample_rate`, plus the usual
`mode` / `webhook_url` / `wait_timeout_seconds` communication fields.

Default `mode` is **`async`**. Pass `mode: "sync"` to wait up to **30
seconds** for a `200` finished job, or get `202` and poll.

```bash
curl -X POST https://api.sume.com/v1/audio-detach \
  -H "Authorization: Bearer $SUME_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: audio-detach-001" \
  -d '{
    "video_url": "https://media.sume.com/artifacts/artf_demo/talk.mp4"
  }'
```

A successful submit returns a job (`request_id` is the job id). When
`result_ready`, `GET /v1/jobs/:id/result` is `kind: audio_detach` with
`audio_url` (new `artf_`), `duration_seconds`, `format`, `channels`,
`sample_rate` (null when omitted — inherited from the source),
`source_duration_seconds`, and optional `range` / `warnings[]`.

Public rate: **$0.01 per job** (`AUDIO_DETACH_PUBLIC_PRICING`; confirm
live in `GET /v1/catalog`). No provider inference — worker ffmpeg only.

## Program

| Field | Effect |
|---|---|
| `format` | `wav` (default, `pcm_s16le` sample-exact) or `mp3` (128 kbps). |
| `range` | Optional `{ start, end? }` seconds. Omit for the whole track. `end` open-ended when omitted. |
| `channels` | `source` (default) or `mono`. |
| `sample_rate` | `16000` \| `44100` \| `48000`. Omit to inherit the source. `16000` + `channels: "mono"` is the STT shape. |

Caps (from `packages/api-contract/src/index.ts`): source ≤ **1800** s;
output ≤ **900** s. A whole track past 900 s needs a `range`.

A source with no audio track fails `detach_source_has_no_audio`. Check
`probe.has_audio` first with [video inspect](/models/video-inspect)
(`frames: false` is enough).

## Refusals (stable codes)

| Code | When |
|---|---|
| `audio_detach_range_empty` | `range.end` ≤ `range.start`, or the range is longer than 900 s. |
| `detach_source_has_no_audio` | Source has no audio track (worker). |
| `detach_start_past_source` | `range.start` is past the probed duration (worker). |
| `ffmpeg_fields_rejected` | Client sent `af` / `filter` / `ffmpeg` / `cmd` / `codec` / friends. The server compiles ffmpeg. |
| `unsupported_media_source` | `video_url` is not on the Sume media host. |
| `source_not_found` | Dead or foreign `media.sume.com` URL. |
| `unsupported_media_type` | HEAD is not a video. |
| `source_duration_exceeded` | Source longer than 1800 s (worker). |

Off-host URLs (`https://example.com/…`) are rejected at admit. Import first.

## Not this surface

| Need | Use |
|---|---|
| Probe / stills / optional STT | [Video inspect](/models/video-inspect) |
| Exact frame at `t`, source size | [Video frames](/models/video-frames) |
| A new MP4 cut | [Video trim](/models/video-trim) |
| Pixel pass (dim / crop) | [Video filter](/models/video-filter) |
| Many audio ranges from one track | Detach once, then [timeline audio](/models/timeline-audio) `operation: "split"` |
| Sequence several clips | [Timeline 1.0](/models/timeline) |

## Related

- [Video inspect](/models/video-inspect)
- [Video frames](/models/video-frames)
- [Video trim](/models/video-trim)
- [Video filter](/models/video-filter)
- [Timeline 1.0](/models/timeline)
- [Timeline audio](/models/timeline-audio)
- [Media inputs](/workflows/asset-library)
- [Jobs and results](/workflows/jobs-and-results)
- [MCP tools and gates](/mcp/tools-and-gates)
