> ## Documentation Index
> Fetch the complete documentation index at: https://assemblyai.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Transcribe live audio

> Upload audio to the Sync API as it is recorded, so the transcript is ready almost as soon as the speaker stops.

## Overview

[`transcribe()`](/docs/sync-stt/getting-started/transcribe-a-short-audio-file) needs the whole clip before it can send anything. `transcribe_live()` starts the request on the first chunk and uploads audio as your code produces it, so by the time the speaker stops, most of the work is already done. What is left to wait for is the tail of the audio.

Both return the same result and post to `POST https://sync.assemblyai.com/v1/transcribe/live`.

<Note>
  **For short audio only**

  Live upload is for short clips: the Sync API caps audio at 120 seconds, and it
  returns one finished transcript when the audio ends. If you need words back
  *while* the speaker is still talking, or you need to capture more than 2 minutes
  of audio, use the
  [Real-time STT API](/docs/streaming/getting-started/transcribe-streaming-audio), which
  opens a WebSocket connection for up to 3 hours.

  It is worth using only when the audio is genuinely still being produced.
  Streaming a file that already exists on disk is slower than
  [`transcribe()`](/docs/sync-stt/getting-started/transcribe-a-short-audio-file), which
  sends it in one piece.
</Note>

## Before you begin

To complete this guide, you need:

* **An API key** — copy it from [API Keys](https://www.assemblyai.com/dashboard/home) and set it once:

  ```bash theme={null}
  export ASSEMBLYAI_API_KEY=<your-key>
  ```

* **A live audio source** — a microphone, an in-progress call, an upload from a browser. This guide uses the microphone.

* **Python 3.8+** for the Python SDK, or **Node.js 18+** for the JavaScript SDK.

* The microphone examples use [`sounddevice`](https://python-sounddevice.readthedocs.io/) (Python) and [SoX](https://sourceforge.net/projects/sox/) (JavaScript). Any source that hands you audio chunks works.

## Transcribe live audio

`transcribe_live()` in Python and `transcribeLive()` in JavaScript take a source that produces audio over time, upload each chunk as it arrives, and return the transcript once the source ends.

Microphone audio is raw PCM with no header, so the config names the sample rate and channel count.

<Tabs groupId="language">
  <Tab language="python-sdk" title="Python SDK" default>
    The source is any iterable of `bytes`. This generator records from the default microphone until you press Enter. The capture callback puts each chunk on a queue and the generator drains it, so recording continues while `transcribe_live()` is busy on the network. A blocking `read()` inside the generator would instead overflow the device buffer and silently drop audio whenever the upload stalls:

    ```python theme={null}
    import queue
    import threading

    import sounddevice as sd  # pip install sounddevice

    from assemblyai.sync.v1 import SyncTranscriber, SyncTranscriptionConfig

    RATE = 16000
    config = SyncTranscriptionConfig(sample_rate=RATE, channels=1)


    def microphone():
        """Yield raw 16-bit PCM from the default microphone until Enter is pressed."""
        chunks = queue.Queue()

        def stop():
            input("Recording. Speak now, then press Enter to stop... ")
            chunks.put(None)

        with sd.RawInputStream(
            samplerate=RATE, channels=1, dtype="int16",
            callback=lambda data, *_: chunks.put(bytes(data)),
        ):
            threading.Thread(target=stop, daemon=True).start()
            while (chunk := chunks.get()) is not None:
                yield chunk


    result = SyncTranscriber().transcribe_live(microphone(), config=config)
    print(result.text)
    ```
  </Tab>

  <Tab language="javascript-sdk" title="JavaScript SDK">
    The source is any async iterable, Node `Readable`, or web `ReadableStream`. Node has no built-in microphone, so this example uses [SoX](https://sourceforge.net/projects/sox/) to record raw PCM to stdout and passes that stream straight in:

    ```javascript theme={null}
    import { spawn } from "node:child_process";
    import { AssemblyAI } from "assemblyai";

    const client = new AssemblyAI({ apiKey: process.env.ASSEMBLYAI_API_KEY });

    // Records 16 kHz, 16-bit, mono PCM to stdout until the process exits.
    const microphone = spawn("sox", [
      "--default-device", "--no-show-progress",
      "--rate", "16000", "--channels", "1",
      "--encoding", "signed-integer", "--bits", "16", "--type", "raw", "-",
    ]);

    console.log("Recording. Speak now, then press Ctrl+C to stop...");
    process.on("SIGINT", () => microphone.kill()); // ends the stream

    const result = await client.sync.transcribeLive(microphone.stdout, {
      sample_rate: 16000,
      channels: 1,
    });
    console.log(result.text);
    ```
  </Tab>
</Tabs>

Run it, say a sentence, and the transcript prints when the recording ends.

### Use your own audio source

The call is the same for any source that produces audio over time. Replace the microphone with whatever you already have:

<Tabs groupId="language">
  <Tab language="python-sdk" title="Python SDK" default>
    ```python theme={null}
    # Frames from a phone call, a WebSocket, or a file still being written.
    result = transcriber.transcribe_live(frames_from_call(), config=config)
    ```

    `async` generators work too, with `AsyncSyncTranscriber.transcribe_live()`.
  </Tab>

  <Tab language="javascript-sdk" title="JavaScript SDK">
    ```javascript theme={null}
    // A browser posting PCM to your server as it records: `req` is a Readable.
    const result = await client.sync.transcribeLive(req, {
      sample_rate: 16000,
      channels: 1,
    });
    ```

    A `fetch` response body or an async generator over WebSocket messages works the same way.
  </Tab>
</Tabs>

If your audio arrives through a **callback** rather than something you can iterate, such as a capture library or a WebRTC track, open a session instead: `open_live()` returns an object you `write()` each chunk to and `close()` when the speaker stops. The [Quickstart](/docs/sync-stt/getting-started/quickstart) has a runnable microphone version.

<Note>
  Ending the source normally uploads everything you sent. To throw a recording
  away without transcribing it, because the user cancelled or the call dropped,
  use `session.abort()`; `result()` then raises.
</Note>

Audio you already hold in full, such as a buffer, a `Blob`, or a file on disk, belongs in [`transcribe()`](/docs/sync-stt/getting-started/transcribe-a-short-audio-file). Streaming a finished clip is slower than sending it whole.

## What to keep in mind

* **Keep producing until you're done.** An upload that goes silent for too long is aborted server-side. Finish by ending the source (or calling `close()`), not by pausing it.
* **The saving comes from overlap.** All but the last speech segment are transcribed while you record, so the win grows with clip length. Below roughly a minute there is only one segment, so the only saving is the elided upload.
* **Errors can surface mid-upload.** Authorization, rate-limit, and capacity failures can arrive part-way through the upload rather than at the end, as a `SyncTranscriptError`. Call [`warm()`](/docs/sync-stt/connection-pre-warming) before you start recording to open the connection ahead of time.
* **The audio limit is unchanged.** The Sync API still caps audio at 120 seconds. The default request budget is 180 seconds, covering the recording as well as the transcription.

## Next steps

* [Transcribe a short audio file](/docs/sync-stt/getting-started/transcribe-a-short-audio-file) — the buffered path, for audio you already hold whole
* [Connection pre-warming](/docs/sync-stt/connection-pre-warming) — open the connection before recording starts
* [Prompting and keyterms](/docs/sync-stt/prompting-and-keyterms) — improve accuracy with contextual prompts and keyterm biasing
* [Word timestamps](/docs/sync-stt/word-timestamps) — get per-word `start`/`end` timings
* [Error handling](/docs/sync-stt/error-handling) — status codes and retry guidance
* [API reference](/docs/api-reference/sync-api/transcribe-live) — full endpoint documentation

## Need help?

If you get stuck, contact our support team at [support@assemblyai.com](mailto:support@assemblyai.com) or create a [support ticket](https://www.assemblyai.com/contact/support). Include the `session_id` from the response to help us look up your request.
