calesthio/openai-audio
Produce and understand audio with OpenAI request-based audio APIs and audio-capable chat models, including text-to-speech, transcription, translation, multimodal audio input/output, model routing, prompt and performance direction, artifact custody, approval gates, and safety/rights review. Use for non-realtime OpenAI audio production; route continuous live voice agents to the separate realtime voice skill.
npx skills add https://github.com/calesthio/generative-media-skills --skill openai-audio
Use this skill when a user wants OpenAI audio production or understanding in a bounded request: generated narration, spoken product demos, podcast or interview transcription, subtitle timing, translation to English, audio QA, or adding audio input/output to an existing chat workflow.
Do not use this as the primary guide for continuous low-latency speech-to-speech agents, live interpreting, SIP/WebRTC sessions, or voice activity detection. Those belong to the separate realtime voice skill. This skill may still explain the boundary: request-based audio APIs fit files, scripts, and bounded requests; realtime sessions fit open connections with live audio events. Documented source: OpenAI’s audio guide distinguishes request-based APIs, realtime sessions, and multimodal chat completions; verified 2026-07-10: https://developers.openai.com/api/docs/guides/audio
Treat the following as documented facts verified on 2026-07-10 from OpenAI public docs:
POST /v1/audio/speech; it accepts gpt-4o-mini-tts, the current pinned snapshot gpt-4o-mini-tts-2025-12-15, tts-1, and tts-1-hd, and supports built-in voices plus custom voice IDs where available. Speech input is limited to 4,096 characters. The older pinned snapshot gpt-4o-mini-tts-2025-03-20 is scheduled to shut down on 2026-07-23 with gpt-4o-mini-tts-2025-12-15 as its documented substitute; do not confuse that snapshot retirement with retirement of the unpinned alias. Sources: https://developers.openai.com/api/reference/resources/audio/subresources/speech/methods/create and https://developers.openai.com/api/docs/deprecationsgpt-4o-mini-tts supports instruction-style voice control; the older tts-1 and tts-1-hd models do not support the instructions parameter. Source: https://developers.openai.com/api/reference/resources/audio/subresources/speech/methods/create/v1/audio/speech are documented as mp3, opus, aac, flac, wav, and pcm; speed ranges from 0.25 to 4.0; streaming format can be sse or audio, with SSE not supported for tts-1/tts-1-hd. Source: https://developers.openai.com/api/reference/resources/audio/subresources/speech/methods/createPOST /v1/audio/transcriptions; documented models include gpt-4o-transcribe, gpt-4o-mini-transcribe, gpt-4o-transcribe-diarize, and whisper-1, with response-format and streaming differences by model. File uploads are limited to 25 MB; split or compress larger inputs without cutting mid-sentence. Source: https://developers.openai.com/api/docs/guides/speech-to-textgpt-4o-transcribe-diarize does not support prompt, logprobs, or timestamp_granularities[]; input longer than 30 seconds requires chunking_strategy, with "auto" recommended. Source: https://developers.openai.com/api/docs/guides/speech-to-textwhisper-1; streamed transcription emits transcript delta/done events. Source: https://developers.openai.com/api/docs/guides/speech-to-textPOST /v1/audio/translations; the API reference states that only whisper-1 is currently available for translation to English, even though shared model type enums may list additional audio model IDs. Source: https://developers.openai.com/api/reference/resources/audio/subresources/translations/methods/creategpt-audio-1.5 with modalities: ["text", "audio"], an audio object for voice/format, and input_audio content blocks for audio input. Source: https://developers.openai.com/api/docs/guides/audiogpt-realtime-2.1, live translation to gpt-realtime-translate, and live transcription to gpt-realtime-whisper. Source: https://developers.openai.com/api/docs/guides/realtimegpt-4o-transcribe and gpt-4o-mini-transcribe by token with estimated per-minute costs. Always re-check before quoting costs in production. Source: https://developers.openai.com/api/docs/pricing/v1/audio/transcriptions and /v1/audio/translations have no abuse-monitoring retention while /v1/audio/speech has 30-day abuse-monitoring retention by default; verified 2026-07-10. Source: https://developers.openai.com/api/docs/guides/your-dataTreat the following as production heuristics, not OpenAI guarantees:
gpt-4o-mini-tts first when the creative brief needs performance direction, expressive control, or iteration through natural-language voice notes.tts-1 only when low latency matters more than quality or detailed direction; use tts-1-hd only when an older integration already depends on it or when tests prove it wins for the specific voice/script.gpt-4o-transcribe when accuracy, proper nouns, or speaker-ready output is more important than cost; use gpt-4o-mini-transcribe for volume, rough cuts, drafts, and cost-sensitive batch transcription; use gpt-4o-transcribe-diarize when speaker labels matter.whisper-1 when you need translation-to-English or word/segment timestamp formats that are documented for whisper-1; otherwise prefer the newer transcription models after testing on representative audio.Ask or infer these variables before choosing an endpoint:
Decision table:
| User intent | Primary route | Model/API choice | Notes |
|---|---|---|---|
| Generate narration or a spoken line from text | /v1/audio/speech | Usually gpt-4o-mini-tts | Best fit for file output, batch narration, style-directed voice performance. |
| Generate low-latency speech in an older simple TTS integration | /v1/audio/speech | tts-1 | Accept lower quality; do not send instructions. |
| Generate speech when an older high-quality TTS path is required | /v1/audio/speech | tts-1-hd | Test against gpt-4o-mini-tts; do not assume “HD” beats a newer model for every brief. |
| Transcribe a file or bounded upload | /v1/audio/transcriptions | gpt-4o-transcribe or gpt-4o-mini-transcribe | Use model selection by accuracy/cost; request only supported response formats. |
| Transcribe with speaker labels | /v1/audio/transcriptions | gpt-4o-transcribe-diarize | Use diarized_json when speaker annotations are required. |
| Create word/segment timestamps for captions | /v1/audio/transcriptions | Often whisper-1 with verbose_json and timestamp granularities | Docs say timestamp granularities require verbose_json; word timestamps add latency. |
| Translate non-English audio to English | /v1/audio/translations | whisper-1 | The translation endpoint is not general localization dubbing; it produces English text. |
| Add audio input/output to an existing chat app | Chat Completions | gpt-audio-1.5 with modalities and audio | Use when the model must reason over audio and respond in text/audio in one chat turn. |
| Build live speech-to-speech, live translation, live transcription, SIP, WebRTC, or VAD | Realtime API | Route out of this skill | Use the separate realtime voice skill. |
Never silently substitute a route. If the approved path is blocked, say what failed, whether it is model access, parameter incompatibility, policy, privacy, cost, or product mismatch, and ask before switching endpoint or model.
Write for spoken performance before prompting. A TTS model can render pacing and tone, but it cannot rescue a script that is visually written, over-punctuated, or full of unexpanded abbreviations.
Production heuristics:
Example performance brief shape:
Voice: coral
Model: gpt-4o-mini-tts
Format: wav for editing; mp3 only for review copies
Performance instructions:
Warm, confident startup launch voice. Conversational, not announcer-like.
Medium pace, lightly excited on the first sentence, then grounded.
Pronounce "Aster Lane" as "ASS-ter lane"; pronounce "SOC 2" as "sock two".
Do not impersonate any real person or named celebrity.
Documented controls:
alloy, ash, ballad, coral, echo, fable, onyx, nova, sage, shimmer, verse, marin, and cedar; the TTS guide notes that voice availability depends on model, and older tts-1/tts-1-hd support a smaller set. Sources: https://developers.openai.com/api/reference/resources/audio/subresources/speech/methods/create and https://developers.openai.com/api/docs/guides/text-to-speechmarin or cedar for best quality; verified 2026-07-10. Source: https://developers.openai.com/api/docs/guides/text-to-speechinstructions field has a documented maximum length of 4096 characters and does not work with tts-1 or tts-1-hd. Source: https://developers.openai.com/api/reference/resources/audio/subresources/speech/methods/createDo not describe voices only by demographic labels. Describe the performance role the production needs:
Select 2 or 3 candidate voices, generate short auditions from the same representative line, and get approval before full-run generation. Use the exact final script or a dense excerpt, not a generic demo sentence, because pronunciation and pacing failures often appear only in the real copy.
Approval gate for public-facing voice:
For a custom voice, also confirm organization eligibility, retain the provider consent-recording ID, verify that the actor in the consent and sample recordings is the same person, and follow the Text-to-Speech Supplemental Agreement. A general email approval is not a substitute for OpenAI's required consent-recording workflow.
Use format by lifecycle:
wav or flac: editing masters, archival custody, downstream mixing.mp3 or aac: web preview, social draft, compact delivery.opus: speech-heavy streaming or low-bitrate distribution when supported by the target.pcm: low-level audio pipelines that require raw PCM.Record every generated audio artifact with:
Do not overwrite approved masters. If you regenerate a line, create a new versioned file and update the manifest.
User intent: create one public-facing launch voiceover line, with approval before batch generation.
Model and endpoint: /v1/audio/speech, gpt-4o-mini-tts, voice marin, WAV master.
This call is the audition/sample, not authorization for a full batch. Run it only after the rights, disclosure, storage, and sample-cost preflight above; require recorded approval of this take before expanding the run.
Python example:
from pathlib import Path
from openai import OpenAI
client = OpenAI()
script = (
"Aster Lane turns every customer call into a searchable product signal, "
"so your team can fix what matters first."
)
instructions = (
"Speak as a warm, credible product-launch narrator. "
"Confident but not hypey. Medium pace. "
"Pronounce Aster as ASS-ter. "
"Do not imitate any real person."
)
out = Path("artifacts/audio/aster-lane-launch-v001.wav")
out.parent.mkdir(parents=True, exist_ok=True)
with client.audio.speech.with_streaming_response.create(
model="gpt-4o-mini-tts",
voice="marin",
input=script,
instructions=instructions,
response_format="wav",
speed=1.0,
) as response:
response.stream_to_file(out)
Why it is structured this way:
Review criteria:
Documented facts:
/v1/audio/transcriptions accepts audio file objects in formats listed by the API reference, including common compressed and uncompressed audio formats. Source: https://developers.openai.com/api/reference/resources/audio/subresources/transcriptions/methods/creategpt-4o-transcribe and gpt-4o-mini-transcribe support only json, while the current speech-to-text guide says json or plain text and includes text examples. Treat this first-party mismatch as volatile: use json for portable production code unless a current account test confirms text. gpt-4o-transcribe-diarize supports json, text, and diarized_json, with diarized_json required for speaker annotations. Sources: https://developers.openai.com/api/reference/resources/audio/subresources/transcriptions/methods/create and https://developers.openai.com/api/docs/guides/speech-to-textwhisper-1 supports timestamp granularities with response_format="verbose_json"; OpenAI’s guide says timestamp_granularities[] is only supported for whisper-1. Sources: https://developers.openai.com/api/docs/guides/speech-to-text and https://developers.openai.com/api/reference/resources/audio/subresources/transcriptions/methods/createProduction heuristics:
prompt, use a prompt-capable transcription model for the isolated repair and reconcile its text with the diarized timeline manually.Use prompt to guide style, spelling, jargon, or continuation from previous segments. The prompt should match the audio language for transcription. Do not use the prompt to invent content or “fix” unclear audio; mark inaudible spans in post-review when necessary.
Good prompt contents:
Example:
This is an English product interview about Aster Lane, SOC 2, Snowflake, Zendesk, and call summarization. Preserve product names. Use "Aster Lane" not "Asterlane". Use "SOC 2" not "sock two" in the transcript.
User intent: transcribe a 35-minute customer interview and preserve speaker turns for a researcher.
Model and endpoint: /v1/audio/transcriptions, gpt-4o-transcribe-diarize, diarized_json.
Python example:
from pathlib import Path
from openai import OpenAI
client = OpenAI()
audio_path = Path("raw/customer-interview-2026-07-10.m4a") # Prevalidated at <25 MB.
with audio_path.open("rb") as audio_file:
transcript = client.audio.transcriptions.create(
model="gpt-4o-transcribe-diarize",
file=audio_file,
response_format="diarized_json",
chunking_strategy="auto",
)
Path("artifacts/transcripts/customer-interview-diarized-v001.json").write_text(
transcript.model_dump_json(indent=2),
encoding="utf-8",
)
Expected result:
Likely failure modes:
Repair:
User intent: create caption timing for a short tutorial clip where word-level karaoke highlighting is required.
Model and endpoint: /v1/audio/transcriptions, whisper-1, verbose_json, timestamp_granularities=["word"].
Python example:
from pathlib import Path
from openai import OpenAI
client = OpenAI()
with open("exports/tutorial-voice.wav", "rb") as audio_file:
transcription = client.audio.transcriptions.create(
model="whisper-1",
file=audio_file,
response_format="verbose_json",
timestamp_granularities=["word"],
prompt=(
"Tutorial narration about Aster Lane, SOC 2, and Zendesk. "
"Use product capitalization exactly."
),
)
Path("artifacts/captions/tutorial-word-timestamps-v001.json").write_text(
transcription.model_dump_json(indent=2),
encoding="utf-8",
)
Why this route:
whisper-1.The audio translations endpoint translates audio into English text. Do not present it as multilingual dubbing, voice conversion, or localized audio production.
Use it when:
Do not use it when:
Complete example:
from pathlib import Path
from openai import OpenAI
client = OpenAI()
with open("raw/founder-clip-es.m4a", "rb") as audio_file:
translation = client.audio.translations.create(
model="whisper-1",
file=audio_file,
response_format="text",
prompt=(
"The speaker discusses Aster Lane, customer support analytics, "
"and SOC 2. Translate to clear English while preserving product names."
),
)
Path("artifacts/transcripts/founder-clip-english-v001.txt").write_text(
translation,
encoding="utf-8",
)
Approval rule: if the translation will be published, require bilingual review or explicit user acceptance that the machine translation may miss nuance.
Use Chat Completions with an audio-capable model when audio is part of a conversational model turn, not merely a file conversion job. Documented pattern: use gpt-audio-1.5, set modalities to include audio, provide audio output parameters, and include audio inputs as base64 input_audio content blocks. Source: https://developers.openai.com/api/docs/guides/audio
Use this route for:
Do not use this route for:
/v1/audio/transcriptions is simpler;/v1/audio/speech is simpler;Complete example:
import base64
from pathlib import Path
from openai import OpenAI
client = OpenAI()
audio_bytes = Path("raw/user-question.wav").read_bytes()
encoded_audio = base64.b64encode(audio_bytes).decode("utf-8")
completion = client.chat.completions.create(
model="gpt-audio-1.5",
modalities=["text", "audio"],
audio={"voice": "alloy", "format": "wav"},
messages=[
{
"role": "system",
"content": (
"Answer as a concise support coach. If the recording is unclear, "
"say what you could not determine rather than guessing."
),
},
{
"role": "user",
"content": [
{"type": "text", "text": "What is the customer asking for?"},
{
"type": "input_audio",
"input_audio": {
"data": encoded_audio,
"format": "wav",
},
},
],
},
],
)
message = completion.choices[0].message
Path("artifacts/chat-audio/answer-transcript-v001.txt").write_text(
message.audio.transcript,
encoding="utf-8",
)
Path("artifacts/chat-audio/answer-v001.wav").write_bytes(
base64.b64decode(message.audio.data)
)
Custody note: chat audio responses include base64 audio bytes and a transcript. Store both if the output is an approved production artifact. If privacy policy requires no server-side persistence, verify store behavior and the organization’s data controls before use.
Documented cost facts are volatile; always re-check pricing on the day of production. On 2026-07-10, OpenAI’s pricing page lists:
gpt-4o-transcribe and gpt-4o-mini-transcribe, including estimated per-minute rates;Production heuristics:
Hard requirements:
Data-control facts verified 2026-07-10:
/v1/audio/transcriptions and /v1/audio/translations with no abuse-monitoring retention and no application-state retention./v1/audio/speech with 30-day abuse-monitoring retention and no application-state retention.Use this protocol for any production asset, public-facing content, customer content, regulated transcript, or paid batch job.
Before generation or transcription:
After a sample:
After a full batch:
Minimal artifact manifest shape:
{
"artifact_id": "narration_sc01_v003",
"created_at": "2026-07-10T18:30:00Z",
"provider": "openai",
"endpoint": "/v1/audio/speech",
"model": "gpt-4o-mini-tts",
"voice": "marin",
"input_script": "scripts/narration/sc01_v004.txt",
"instructions": "Warm, credible, medium pace; pronounce Aster as ASS-ter.",
"parameters": {
"response_format": "wav",
"speed": 1.0
},
"outputs": [
{
"path": "artifacts/audio/sc01_v003.wav",
"role": "raw_model_master",
"sha256": "..."
}
],
"approval": {
"status": "approved",
"approver": "user",
"approved_at": "2026-07-10T18:45:00Z"
},
"source_verification": {
"docs_checked_at": "2026-07-10",
"pricing_checked_at": "2026-07-10"
}
}
For generated speech, review:
For transcripts, review:
For translated transcripts, review:
| Failure | Likely cause | Repair |
|---|---|---|
| TTS mispronounces a product name | Name not phonetically constrained | Add pronunciation in instructions and/or script; regenerate only affected lines. |
| TTS sounds like an ad read | Direction too broad: “excited”, “professional” | Specify audience, emotional arc, pace, and what to avoid. |
| TTS chunks do not match | Direction changed between chunks or script boundaries were unnatural | Lock one instruction block and chunk at scene/paragraph boundaries. |
| Output format wrong for edit | Delivery format chosen too early | Generate WAV/FLAC master; transcode copies downstream. |
| Transcript misses proper nouns | No vocabulary prompt or poor audio | Add vocabulary prompt; retry clean segments; manually QA final. |
| Timestamps unavailable | Wrong model/response format | Use documented timestamp route: whisper-1, verbose_json, requested granularities. |
| Streaming request ignored | whisper-1 used | Use a GPT transcription model for streaming, or accept non-streaming Whisper behavior. |
| Translation requested to non-English target | Endpoint mismatch | Use translation endpoint only for English text, or route to a localization/dubbing workflow outside this skill. |
| Speaker labels treated as identity | Misuse of diarization | Human-review speaker mapping; never use diarization as biometric ID. |
| Privacy blocker | Sensitive source audio or unclear consent | Pause, confirm lawful basis, storage, retention, and disclosure requirements. |
When handing off results, include:
Take calesthio/openai-audio from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.