Generate music credits for a podcast episode

Source: AudD•

Generate music credits for a podcast episode

Produce a timestamped music credits list for a podcast episode with the AudD enterprise endpoint, collapsing repeated matches into one credit per song.

Podcasts use music: intros, stingers, bumpers, beds under the host, a song played in full during a segment. This recipe takes one episode audio file and produces a credits list — every song that appears, with a timestamp, artist, title, and label — ready to drop into your show notes or your licensing records.

What you’ll build

A script that sends a podcast episode to AudD’s enterprise endpoint, walks the matches it returns, collapses runs of the same song into a single credit with a time range, and prints a clean credits block.

The enterprise endpoint is the right tool here (not the standard endpoint): an episode is arbitrary length, and you want every song in it, not one. recognize_enterprise returns a flat list[EnterpriseMatch] — one entry per recognized fragment, in time order — and each match carries its position in your episode directly as start_seconds / end_seconds. A two-minute outro song spans several consecutive matches, so you’ll get several near-identical entries for it; the dedupe step turns those back into one line that reads “used from 48:00 to 50:00.”

The show-notes timestamps come straight from those matches: start_seconds and end_seconds are the song’s position in your episode, in seconds. recognize_enterprise requests accurate offsets by default, so there’s no offset math to do — you read those values and group on them.

Prerequisites

  • An API token from dashboard.audd.io. Get your own token there; the enterprise endpoint must be enabled on it. label comes back on enterprise responses; ISRC and UPC require a Startup plan or higher if you also want to log those for licensing.
  • Python 3.10+ with the SDK: pip install audd
  • A podcast episode file or URL. https://audd.tech/example.mp3 is a public, reproducible file you can run against to see the full flow before you point it at your own audio.

Walkthrough

Step 1: Recognize the episode

Point recognize_enterprise at the episode — a URL, file bytes, or a path. It scans the whole file and returns a flat list[EnterpriseMatch], one entry per recognized fragment in time order, each with a file-absolute start_seconds / end_seconds (accurate offsets are requested by default).

The output is one line per recognized fragment. Stretches of pure speech (the host talking with no music bed) produce no match — that’s a gap, not an error. A song that plays for two minutes shows up as a run of consecutive matches with the same artist and title but advancing start_seconds values; that repetition is exactly what Step 3 folds away.

Always set limit during development. The enterprise endpoint bills per 12 seconds of audio processed. A 90-minute episode is hundreds of fragments; an unbounded call meters all of them. Develop against limit=20, confirm your credits logic, and only then raise the cap for a full pass.

Always set limit during development. The enterprise endpoint bills per 12 seconds of audio processed. A 90-minute episode is hundreds of fragments; an unbounded call meters all of them. Develop against limit=20, confirm your credits logic, and only then raise the cap for a full pass.

Step 2: Understand the time fields

Before deduping, get the time fields straight — they are easy to confuse and the credits block depends on using the right one.

  • start_seconds / end_seconds — where this song plays in your episode, in seconds (e.g. 64.2 to 71.6). These are the values you put in the show notes; a fragment that arrived without a usable position has None here.
  • start_offset / end_offset — raw milliseconds within AudD’s internal 12-second scan fragment, which the seconds are derived from. Not episode seconds, and rarely needed.
  • timecode — the position inside the matched song where the fragment lined up (e.g. 00:41 means the fragment matched 41 seconds into that song). Useful for knowing which part of a song was used, but it is not a position in your episode.

Everything below keys off start_seconds and end_seconds.

Step 3: Collapse consecutive matches into one credit

The dedupe rule: walk the matches in time order; whenever the current match has the same artist and title as the credit you’re currently building, extend that credit’s end time instead of starting a new one. A new artist/title starts a new credit.

The result is one entry per distinct song, in the order it first appears, with the span it occupied. The SDK parses responses leniently — any field can be absent or None — hence the start_seconds guard and the end_seconds fallback, which keep a positionless fragment from crashing the pass.

A song that recurs gets two credits, on purpose. If the same theme plays at the open and again at the close, two non-adjacent runs produce two credits. That’s usually what you want in show notes — “used at 00:00 and again at 48:00.” If you’d rather merge all appearances of a song into one line, group the finished credits by (artist, title) afterward.

A song that recurs gets two credits, on purpose. If the same theme plays at the open and again at the close, two non-adjacent runs produce two credits. That’s usually what you want in show notes — “used at 00:00 and again at 48:00.” If you’d rather merge all appearances of a song into one line, group the finished credits by (artist, title) afterward.

Step 4: Render the credits block

Format each credit as a timestamp range plus artist, title, and label.

This prints a block like:

Songs that played only behind a few seconds of speech collapse to a short span; a full segment track collapses to its real run. Either way you get one line per song.

Step 5: Skip the cold open, sample long beds

Two parameters keep the cost and the noise down on real episodes. Pass them as keyword arguments to recognize_enterprise:

  • skip_first_seconds starts recognition partway in — handy if every episode opens with the same dynamically-inserted ad you don’t want to credit.
  • every and skip sample the file: every=1, skip=4 recognizes one fragment then skips the next four (one match per minute). For credits you usually want full coverage so you don’t miss a short stinger, but for a rough “what music is in here” pass, sampling cuts metered fragments several-fold.

Note skip_first_seconds must not be combined with use_timecode; use one or the other.

What you get back

Each entry in the returned list is one recognized fragment, in time order. The fields a credits list cares about:

For the example file, a match might come back with start_seconds = 0.0, end_seconds = 57.0, artist = "Tears For Fears", title = "Everybody Wants To Rule The World", and label = "UMC (Universal Music Catalogue)" — which renders as the single credit line above.

Handling errors

The SDK raises typed exceptions; catch the ones you can act on.

  • Authentication errors (AudDAuthenticationError) — bad or missing token. Fail at startup, not per episode.
  • Quota / subscription errors (AudDSubscriptionError) — you’ve hit a request limit, or the enterprise endpoint isn’t enabled on your token. The enterprise endpoint and ISRC/UPC both depend on plan tier; surface these to the account owner rather than retrying.
  • Invalid-audio errors — the URL or file wasn’t decodable audio. Treat as a bad-input case: report which episode failed and move on.
  • Connection errors (AudDConnectionError) — transient; retry with backoff.

A clean stretch with no music isn’t an error — those fragments simply produce no match, so they contribute no credits.

Going further

  • Persist the finished credits keyed by episode ID so you never re-scan (a re-scan re-meters every fragment).
  • If your show always opens and closes with the same theme, post-process the credits to merge non-adjacent runs of the same (artist, title) into one line.
  • Recognizing a back catalog of episodes? See Enterprise cost optimization for how every, skip, and limit trade coverage against metered fragments.
  • Turning a DJ set or continuous mix into a tracklist instead of a credits block? See Turn a DJ set or mix into a tracklist.
  • Generate a music cue sheet from a video, broadcast, or class recording
  • Turn a DJ set or mix into a tracklist
  • Enterprise cost optimization
  • Standard, enterprise, or streams: how to choose
  • Python SDK docs
  • API reference

What this article says