Nebul Docs

Speech to Text

Transcribe audio to text with word- and segment-level timestamps, subtitle formats, streaming, and speaker diarization

The Speech to Text endpoint (POST /v1/audio/transcriptions) turns audio files into text. Two Parakeet models serve it: nvidia/parakeet-tdt-0.6b-v2 for English, nvidia/parakeet-tdt-0.6b-v3 for 25 languages including Dutch, German, French, and Spanish.

You get plain text by default, word- and segment-level timestamps on request, SRT and WebVTT subtitle formats, SSE streaming while the file processes, and speaker labels via the diarized format. Long files are split automatically on silence, so you never chunk audio yourself.

Every example reads your key from NEBUL_API_KEY; export it first. The Quick Start covers key setup.

Request

POST https://api.inference.nebul.io/v1/audio/transcriptions

The request is multipart:

ParameterTypeRequiredDescription
fileFileYesThe audio file: .flac, .m4a, .mp3, .mp4, .mpeg, .mpga, .ogg, .opus, .wav, or .webm.
modelStringYesnvidia/parakeet-tdt-0.6b-v2 (English) or nvidia/parakeet-tdt-0.6b-v3 (multilingual).
languageStringNoISO 639-1 code, e.g. en, nl, de. Defaults to en. The v3 model also accepts auto for detection; v2 supports en only.
response_formatStringNojson (default), text, verbose_json, srt, vtt, diarized_json.
promptStringNoText to guide the transcription, e.g. spellings of names.
temperatureFloatNoSampling temperature, 0 to 1. Defaults to 0.0.

The v3 language codes: auto, bg, hr, cs, da, nl, en, et, fi, fr, de, el, hu, it, lv, lt, mt, pl, pt, ro, sk, sl, es, sv, ru, uk.

Example

Transcribe an English WAV file:

import os

import requests

response = requests.post(
    "https://api.inference.nebul.io/v1/audio/transcriptions",
    headers={"Authorization": f"Bearer {os.environ['NEBUL_API_KEY']}"},
    files={"file": open("speech.wav", "rb")},
    data={
        "model": "nvidia/parakeet-tdt-0.6b-v3",
        "language": "en",
        "response_format": "json",
    },
)

print(response.json()["text"])

For six seconds of clear English speech, this returns the sentence and a usage block:

{
  "text": "Hello, this is a test of the Nebel speech recognition system, it converts audio into text.",
  "usage": {
    "input_tokens": 5,
    "output_tokens": 16,
    "total_tokens": 21,
    "seconds": 5,
    "type": "duration"
  }
}

A Dutch file with language=nl transcribes Dutch text with the same call shape. Use language=auto when you don't know.

Timestamps

response_format: "verbose_json" adds word and segment timing. Only the parakeet models support it; reson8's variant returns segments without word timings, and cohere-transcribe rejects it with a 400.

response = requests.post(
    "https://api.inference.nebul.io/v1/audio/transcriptions",
    headers={"Authorization": f"Bearer {os.environ['NEBUL_API_KEY']}"},
    files={"file": open("speech.wav", "rb")},
    data={
        "model": "nvidia/parakeet-tdt-0.6b-v3",
        "language": "en",
        "response_format": "verbose_json",
    },
)

result = response.json()
print(f"Language: {result['language']}, duration: {result['duration']}s")
print(f"{len(result['words'])} words, {len(result['segments'])} segments")
{
  "text": "Hello, this is a test of the Nebel speech recognition system, it converts audio into text.",
  "language": "en",
  "duration": 5.9875,
  "words": [
    {
      "word": "Hello,",
      "start_offset": 0,
      "end_offset": 6,
      "start": 0.0,
      "end": 0.48
    },
    {
      "word": "this",
      "start_offset": 8,
      "end_offset": 10,
      "start": 0.64,
      "end": 0.8
    }
  ],
  "segments": [
    {
      "segment": "Hello, this is a test of the Nebel speech recognition system, it converts audio into text.",
      "start_offset": 0,
      "end_offset": 72,
      "start": 0.0,
      "end": 5.76
    }
  ],
  "usage": {
    "input_tokens": 5,
    "output_tokens": 16,
    "total_tokens": 21,
    "seconds": 5,
    "type": "duration"
  }
}
FieldTypeDescription
textStringThe full transcription.
languageStringDetected or requested language code.
durationNumberAudio length in seconds.
words[].wordStringOne recognized word, punctuation attached.
words[].start, words[].endNumberWord timing in seconds.
words[].start_offset, words[].end_offsetIntegerCharacter offsets into text.
segments[].segmentStringThe segment text.
segments[].start, segments[].endNumberSegment timing in seconds.
usageObjectToken counts plus seconds of audio processed.

Subtitles

response_format: "srt" and "vtt" return timed subtitle text:

curl https://api.inference.nebul.io/v1/audio/transcriptions \
  -H "Authorization: Bearer $NEBUL_API_KEY" \
  -F "file=@speech.wav" \
  -F "model=nvidia/parakeet-tdt-0.6b-v3" \
  -F "response_format=srt"
1
00:00:00,000 --> 00:00:05,759
Hello, this is a test of the Nebel speech recognition system, it converts audio into text.

vtt returns the same timings in WebVTT shape with a WEBVTT header. Feed either straight into a video player or subtitle pipeline. Subtitle formats work on the parakeet and reson8 models; cohere-transcribe rejects them.

Streaming

POST /v1/audio/transcriptions/stream takes the same multipart request and returns transcription chunks as Server-Sent Events while the file processes:

import json
import os

import requests

response = requests.post(
    "https://api.inference.nebul.io/v1/audio/transcriptions/stream",
    headers={"Authorization": f"Bearer {os.environ['NEBUL_API_KEY']}"},
    files={"file": open("speech.wav", "rb")},
    data={"model": "nvidia/parakeet-tdt-0.6b-v3"},
    stream=True,
)

for line in response.iter_lines():
    if line and line.startswith(b"data: "):
        payload = line[6:]
        if payload == b"[DONE]":
            break
        chunk = json.loads(payload)
        print(chunk["text"])

Each data: line carries the text recognized so far and its offset in seconds; the stream ends at data: [DONE]. One file upload, incremental results.

A second endpoint, POST /v1/audio/transcriptions/stream_input, accepts a continuous audio stream instead of a complete file. Voice Activity Detection splits it on silence: chunks between 2 and 10 seconds (tunable via min_chunk_seconds and max_chunk_seconds) are transcribed as they arrive. Use it for live microphones and long-running capture.

Speaker diarization

response_format: "diarized_json" labels each segment with a speaker:

{
  "task": "transcribe",
  "duration": 5.9875,
  "text": "A: Hello, this is a test of the Nebel speech recognition system, it converts audio into text.",
  "segments": [
    {
      "type": "transcript.text.segment",
      "id": "seg_001",
      "start": 0.0,
      "end": 5.76,
      "text": "Hello, this is a test of the Nebel speech recognition system, it converts audio into text.",
      "speaker": "A"
    }
  ],
  "usage": {
    "input_tokens": 5,
    "output_tokens": 16,
    "total_tokens": 21,
    "seconds": 5,
    "type": "duration"
  }
}

Speakers are labeled A, B, C in speaking order. Diarization works on the parakeet and reson8 models; cohere-transcribe rejects diarized_json. The Speaker Diarization page covers the format in depth, including its limitations.

Models

Examples on this page use nvidia/parakeet-tdt-0.6b-v3, the default transcription model. The Model Catalog lists the other transcription models with their specs. Response-format support and the usage block vary by model: some models accept only json and text, and not all report token counts.

Errors

StatusMeaning
400Unsupported audio format. The error names the supported extensions: .flac, .m4a, .mp3, .mp4, .mpeg, .mpga, .ogg, .opus, .wav, .webm.
429Rate limited. Retry with exponential backoff.
500Transcription failed. Retry once, then contact support with the x-request-id header.

Better in, better out

Accuracy tracks recording quality. Use 16 kHz or higher sample rates, keep speech at a healthy volume, and minimize background noise. Long files are split automatically on silence, so you never chunk audio yourself.

For generating speech instead of transcribing it, see Text to Speech.

On this page