Skip to main content
skill CX Codex

venice-audio-transcription — Claude Code skill: setup and features

Guides audio transcription via the Venice API with word-level or segment timestamps. Useful for voice notes, podcasts, and subtitle generation.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add veniceai/skills --skill venice-audio-transcription -a claude-code
Open on GitHub

What venice-audio-transcription does

This skill guides speech-to-text processing using the POST /api/v1/audio/transcriptions endpoint. The service accepts containers like mp3, wav, or m4a up to 25 MB in multipart requests. Venice bills transcription per second of audio and delivers outputs as plain text or JSON.

Specifying the model parameter is mandatory; leaving it blank returns a 400 error despite OpenAPI schema defaults. You can select models like nvidia/parakeet-tdt-0.6b-v3 or openai/whisper-large-v3. Enabling the timestamps flag returns timing objects down to word, segment, or character levels depending on the chosen model.

Direct video upload is retired, so video soundtracks need audio extraction first. Because the API does not output raw srt or vtt files, client code must parse the returned JSON timestamps to build captions. Long recordings exceeding the 25 MB cap require splitting with ffmpeg before submission.

What it helps with

  • transcribe speech recordings into text or JSON
  • extract word-level or segment timestamps for captioning
  • call Venice transcription via the OpenAI TypeScript SDK
  • split audio files exceeding 25 MB using ffmpeg

Example prompts for the agent

  • Transcribe meeting.m4a using nvidia/parakeet-tdt-0.6b-v3 and return the output as JSON.
  • Process interview.mp3 with openai/whisper-large-v3 and include word timestamps.
  • Show an OpenAI SDK snippet to send audio.wav to the Venice transcription endpoint.

How to install venice-audio-transcription

1Skills CLI (Vercel)

npx skills add veniceai/skills --skill venice-audio-transcription -a claude-code

2Manually: put the files in place

~/.claude/skills/venice-audio-transcription/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/venice-audio-transcription/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about venice-audio-transcription

How do you install venice-audio-transcription in Claude Code?

Run npx skills add veniceai/skills --skill venice-audio-transcription -a claude-code in your terminal.

What does the venice-audio-transcription skill do?

It provides API patterns and model parameters to convert speech into text through Venice's audio transcription endpoint.

Does the transcription endpoint generate SRT subtitle files directly?

No, Venice only returns json or plain text. To create subtitles, set timestamps=true with JSON output and format the resulting timing arrays into SRT syntax.

Source text

SKILL.md · MIT
---
name: venice-audio-transcription
description: Transcribe audio files to text via POST /audio/transcriptions. Covers supported models (Parakeet, Whisper, Wizper, Scribe, xAI STT), accepted containers (wav/flac/m4a/aac/mp4/mp3/ogg/webm), response formats (json/text only), per-model timestamps (word/segment/char), language hints, the 25 MB cap, and per-audio-second pricing. OpenAI-compatible multipart.
---

# Venice Transcription (`/audio/transcriptions`)

`POST /api/v1/audio/transcriptions` takes an audio file and returns text. It's OpenAI-compatible with `multipart/form-data` — the OpenAI SDK's `audio.transcriptions.create()` works unchanged.

| Method | Path | Auth | Notes |
|---|---|---|---|
| `POST` | `/api/v1/audio/transcriptions` | Bearer key or x402 (SIWX) | `multipart/form-data`, file field `file`, max 25 MB. Billed per second of audio. |

## Use when

- You need STT (speech-to-text) for voice notes, meetings, podcasts, short audio.
- You need word/segment timestamps for subtitles or chapters.
- You want to pick between Venice-hosted Parakeet, Whisper-family models, ElevenLabs Scribe, or xAI STT.

For video, there is no transcription endpoint any more — `POST /video/transcriptions` is retired and returns `410`. Extract the audio track and send it here, or ask a video-capable chat model via [`venice-chat`](../venice-chat/SKILL.md).

## Minimal request

```bash
curl https://api.venice.ai/api/v1/audio/transcriptions \
  -H "Authorization: Bearer $VENICE_API_KEY" \
  -F "file=@./meeting.m4a" \
  -F "model=nvidia/parakeet-tdt-0.6b-v3" \
  -F "response_format=json" \
  -F "timestamps=false"
```

```json
{ "text": "Alright everyone, let's kick off the meeting...", "duration": 184.2 }
```

With `timestamps=true`, the JSON also carries a `timestamps` object (see below).

## Request (`multipart/form-data`)

Only the fields below are read; anything else in the form is ignored.

| Field | Type | Default | Notes |
|---|---|---|---|
| `file` | binary | — | **Required.** Real file part (no base64). Accepted: `wav`/`wave`, `flac`, `m4a`, `aac`, `mp4`, `mp3`, `ogg`/`oga`, `webm`. Checked by extension/MIME and then by binary signature. Max **25 MB**. |
| `model` | string | — | **Send it.** The OpenAPI schema lists `nvidia/parakeet-tdt-0.6b-v3` as default, but that default is never applied: omitting `model` returns `400 "model is required"`. |
| `response_format` | `json` / `text` | `json` | Only these two. `text` returns a `text/plain` body with just the transcript. |
| `timestamps` | bool (`true`/`false` as form string) | `false` | Adds `timestamps` to the JSON response. |
| `language` | string | — | ISO 639-1 hint (`en`, `ja`, …). Forwarded by Whisper, Wizper, Scribe and xAI STT; ignored by Parakeet (auto-detects). |

## Response

```json
{
  "text": "…",
  "duration": 184.2,
  "timestamps": {
    "word":    [{ "word": "Alright", "start": 0.12, "end": 0.48 }],
    "segment": [{ "text": "Alright everyone…", "start": 0.12, "end": 4.9 }],
    "char":    [{ "char": "A", "start": 0.12, "end": 0.15 }]
  }
}
```

`duration` (seconds) and `timestamps` are optional. Which timestamp arrays appear depends on the model:

| Model | Timestamp granularity |
|---|---|
| `openai/whisper-large-v3` | `segment` + `word` |
| `fal-ai/wizper` | `segment` |
| `elevenlabs/scribe-v2` | `word` |
| `stt-xai-v1` | `word` |
| `nvidia/parakeet-tdt-0.6b-v3` | may include `segment`, `word` and/or `char` |

## Models

All five are in the live `GET /models?type=asr` list. Price is `model_spec.pricing.per_audio_second.usd`.

| Model ID | Privacy | Notes |
|---|---|---|
| `nvidia/parakeet-tdt-0.6b-v3` | private | Venice-hosted, fast. Ignores `language`. |
| `openai/whisper-large-v3` | private | Multilingual; `language` hint; segment + word timestamps. |
| `fal-ai/wizper` | private | Whisper v3 variant; `language` hint; segment timestamps. |
| `elevenlabs/scribe-v2` | anonymized | `language` hint; word timestamps. |
| `stt-xai-v1` | anonymized | `language` hint; word timestamps. |

A key with `modelPrivacy: PRIVATE_ONLY` gets `403` on the `anonymized` ones (`PRIVATE_TEXT` keys are not restricted here). Failed transcriptions are not charged.

## OpenAI SDK

```ts
import OpenAI from 'openai'
import fs from 'node:fs'

const client = new OpenAI({
  apiKey: process.env.VENICE_API_KEY,
  baseURL: 'https://api.venice.ai/api/v1',
})

const out = await client.audio.transcriptions.create({
  file: fs.createReadStream('meeting.m4a'),
  model: 'openai/whisper-large-v3',
  response_format: 'json',
  language: 'en',
  // @ts-expect-error — Venice-specific extra, passes through multipart
  timestamps: true,
})

console.log(out.text)
```

## Long files

There's no server-side chunking, and uploads are capped at 25 MB. Split long recordings client-side (on silence, or fixed segments), transcribe each chunk, then concatenate with offset timestamps.

```bash
ffmpeg -i long.mp3 -f segment -segment_time 600 -c copy chunk_%03d.mp3
```

## Errors

| Code | Meaning |
|---|---|
| `400` | Missing `model`, bad params (e.g. `response_format` not `json`/`text`), no `file` part (including a JSON body instead of multipart → `"No audio file provided"`), unsupported extension/MIME, or unrecognized binary signature. |
| `401` | Authentication failed. |
| `402` | Insufficient balance. Bearer → `{"error":"Insufficient USD or Diem balance…"}`, or `"API key USD|DIEM spend limit exceeded…"` when the key's own cap is hit (no `code` field); x402 → `PAYMENT_REQUIRED`. |
| `403` | A `PRIVATE_ONLY` key calling an `anonymized` model, or region restriction. |
| `404` | Unknown `model`. |
| `413` | File larger than 25 MB (`{"code":"PAYLOAD_TOO_LARGE","error":"File exceeds the maximum allowed size of 25 MB."}`). |
| `422` | Upstream provider couldn't process the audio (zero-length, silent, corrupt, unsupported format or language, provider-side refusal). No `suggested_prompt`. |
| `429` | Rate limited. |
| `500` | Inference failure. |
| `502` | Temporary upstream ASR failure — `{"error":"Audio transcription failed due to a temporary upstream error. Please retry."}` (no `code` field). Retry with backoff. |
| `503` | Model temporarily offline — retry with jitter. |

See [`venice-errors`](../venice-errors/SKILL.md) for body shapes and retry strategy.

## Gotchas

- Always send `model` — the documented default never applies.
- `file` must be a real multipart file part. JSON + base64 is **not** supported.
- There is no `verbose_json`, `srt` or `vtt`. For subtitles, use `response_format=json` + `timestamps=true` and render the timings yourself. `text` drops timestamps entirely.
- Check which granularity your model returns before building on `timestamps.word` vs `timestamps.segment`.
- A file with a valid extension but a non-audio binary signature is rejected; re-encode to a standard profile (e.g. MP3 44.1 kHz or 16 kHz).
- On `429`, back off; throttle big batches rather than firing everything in parallel.

© veniceai · MIT · veniceai/skills

Similar skills

All skills for AI and ML →

From the same set23

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor