# How VoiceStudio's Audiobook and Longform Jobs Router Coordinates Chunked Generation and Progress Events

> Discover how VoiceStudio's audiobook and longform jobs router efficiently coordinates chunked generation and progress events. Learn about job record creation and real-time updates via WebSockets.

- Repository: [Palash Debnath/VoiceStudio](https://github.com/debpalash/VoiceStudio)
- Tags: internals
- Published: 2026-09-13

---

**VoiceStudio coordinates chunked generation and progress events by validating incoming requests, creating persistent job records in [`api/routers/job_store.py`](https://github.com/debpalash/VoiceStudio/blob/main/api/routers/job_store.py), and iterating through text segments via `_ChunkedGenerator`, which invokes `_run_engine` for audio synthesis while dispatching real-time updates through WebSocket connections managed by [`api/routers/socket.py`](https://github.com/debpalash/VoiceStudio/blob/main/api/routers/socket.py).**

The VoiceStudio backend, available at `debpalash/VoiceStudio`, handles extensive text-to-speech workloads through specialized FastAPI routers designed for asynchronous job management. These components implement a dual-stream architecture where audio data flows to the client via HTTP chunked transfer encoding while progress metadata transmits through dedicated WebSocket channels. This implementation centers on the coordination logic found in [`api/routers/audiobook.py`](https://github.com/debpalash/VoiceStudio/blob/main/api/routers/audiobook.py) and [`api/routers/longform.py`](https://github.com/debpalash/VoiceStudio/blob/main/api/routers/longform.py).

## Job Initialization and Request Validation

When a client POSTs a generation request to the `/api/audiobook` endpoint, the router validates the payload against model constraints and voice availability. The validation logic ensures text length limits and voice identifiers are properly specified before proceeding.

Upon successful validation, the router creates a job record via the internal task store defined in [`api/routers/job_store.py`](https://github.com/debpalash/VoiceStudio/blob/main/api/routers/job_store.py). This record contains a unique `job_id`, the original request parameters, and a mutable `progress` field initialized to zero. The router returns the `job_id` to the client in the `X-Job-Id` response header, enabling subsequent progress tracking.

## The Chunked Generation Pipeline

The core synthesis logic resides in the `_ChunkedGenerator` async generator implemented in [`api/routers/audiobook.py`](https://github.com/debpalash/VoiceStudio/blob/main/api/routers/audiobook.py). According to the VoiceStudio source code, this generator iterates over the source text and yields binary audio segments through the following sequence:

1. **Text segmentation** – The input is divided into chunks based on configurable size limits or natural chapter boundaries.
2. **Engine invocation** – Each chunk is passed to `_run_engine` in [`api/routers/generation.py`](https://github.com/debpalash/VoiceStudio/blob/main/api/routers/generation.py), which returns a synthesized audio segment.
3. **HTTP streaming** – The audio chunk is immediately yielded to the client through FastAPI's streaming response interface, allowing playback to begin before generation completes.
4. **Progress calculation** – The router updates the job state using `job.progress = int(100 * (chunk_id + 1) / total_chunks)`.

This pipeline ensures efficient memory utilization by processing one chunk at a time rather than holding the entire audiobook in memory.

## Real-Time Progress Broadcasting

Simultaneous with audio generation, the router maintains a progress broadcasting system through WebSocket connections. A background coroutine `_publish_progress` subscribes to a per-job async queue that receives status updates after each chunk completion.

The progress dissemination flow involves:

- **Queue insertion** – After updating `job.progress`, the router pushes a JSON payload containing `job_id`, `progress`, and `chunk_id` onto the progress queue.
- **WebSocket distribution** – The handler defined in [`api/routers/socket.py`](https://github.com/debpalash/VoiceStudio/blob/main/api/routers/socket.py) monitors the queue and broadcasts messages to all clients connected to `/ws/progress/{job_id}`.
- **Client subscription** – Frontend applications establish WebSocket connections using the `job_id` obtained from the initial HTTP response, receiving incremental updates without polling overhead.

This architecture decouples generation workload from progress notification, ensuring that network latency on the progress channel does not block audio synthesis.

## Longform Router Variations

The longform router in [`api/routers/longform.py`](https://github.com/debpalash/VoiceStudio/blob/main/api/routers/longform.py) inherits the chunked generation core but optimizes for continuous streaming scenarios. As implemented in `debpalash/VoiceStudio`, this router adjusts chunk sizes to smaller segments and enables streaming-while-processing, allowing clients to begin playback after the first chunk completes.

While [`api/routers/audiobook.py`](https://github.com/debpalash/VoiceStudio/blob/main/api/routers/audiobook.py) typically processes larger chunks optimized for file download efficiency, the longform variant minimizes initial latency. Both routers share the same [`job_store.py`](https://github.com/debpalash/VoiceStudio/blob/main/job_store.py) interface and WebSocket broadcasting infrastructure, ensuring consistent progress event formatting across endpoints.

## Error Handling and Cancellation

The router implements comprehensive error handling throughout the generation pipeline. If `_run_engine` raises an exception or the client aborts the connection, the router captures the failure and updates the job status to `failed` in [`api/routers/job_store.py`](https://github.com/debpalash/VoiceStudio/blob/main/api/routers/job_store.py).

The cleanup process involves:

- **Status propagation** – A final progress event containing `error` details is pushed to the WebSocket queue before connection closure.
- **Resource cleanup** – Partially generated audio files are removed from temporary storage to prevent disk accumulation.
- **Job finalization** – The job record is marked as terminal, preventing further processing attempts and signaling completion to polling clients.

## Implementation Examples

The following examples demonstrate client interaction and server-side implementation patterns.

### Client-Side Job Initiation

```python
import requests
import websockets
import asyncio
import json

# Initiate generation job

resp = requests.post(
    "https://voice.studio/api/audiobook",
    json={"text": long_text, "voice": "en-US"},
    stream=True,
)
job_id = resp.headers["X-Job-Id"]

# Monitor progress via WebSocket

async def listen_progress():
    async with websockets.connect(
        f"wss://voice.studio/ws/progress/{job_id}"
    ) as ws:
        async for msg in ws:
            data = json.loads(msg)
            print(f"Job {data['job_id']}: {data['progress']}% complete")

asyncio.run(listen_progress())

```

### Server-Side Chunked Generation

```python

# Simplified from api/routers/audiobook.py

async def _ChunkedGenerator(request):
    job = create_job(request.json())
    chunks = split_into_chunks(request.json()["text"])
    total_chunks = len(chunks)
    
    for chunk_id, chunk in enumerate(chunks):
        # Synthesize audio segment

        audio = await _run_engine(chunk, request.json()["voice"])
        
        # Update job progress

        job.progress = int(100 * (chunk_id + 1) / total_chunks)
        
        # Broadcast to WebSocket subscribers

        await progress_queue.put({
            "job_id": job.id,
            "progress": job.progress,
            "chunk_id": chunk_id
        })
        
        # Stream chunk to client

        yield audio

```

## Summary

- **VoiceStudio** handles extensive TTS workloads through [`api/routers/audiobook.py`](https://github.com/debpalash/VoiceStudio/blob/main/api/routers/audiobook.py) and [`api/routers/longform.py`](https://github.com/debpalash/VoiceStudio/blob/main/api/routers/longform.py), which implement chunked generation patterns for memory efficiency.
- The **`_ChunkedGenerator`** function processes text segments sequentially using **`_run_engine`** from [`api/routers/generation.py`](https://github.com/debpalash/VoiceStudio/blob/main/api/routers/generation.py), yielding audio chunks while updating progress state.
- **Progress events** flow through an async queue to WebSocket handlers in [`api/routers/socket.py`](https://github.com/debpalash/VoiceStudio/blob/main/api/routers/socket.py), providing real-time updates via `/ws/progress/{job_id}` endpoints.
- **Job state** persists in [`api/routers/job_store.py`](https://github.com/debpalash/VoiceStudio/blob/main/api/routers/job_store.py), tracking completion percentages and error conditions throughout the generation lifecycle.
- **Longform routing** optimizes chunk sizes for streaming scenarios, while the audiobook router prioritizes throughput for complete file generation.

## Frequently Asked Questions

### How does VoiceStudio handle large text inputs that exceed single-request processing limits?

VoiceStudio automatically segments large inputs into manageable chunks within the `_ChunkedGenerator` function. According to the source code in [`api/routers/audiobook.py`](https://github.com/debpalash/VoiceStudio/blob/main/api/routers/audiobook.py), the router analyzes text length and splits content at logical boundaries before processing each segment independently through `_run_engine`, preventing memory overflow on extensive texts.

### What protocol does VoiceStudio use to stream progress updates to clients?

The system utilizes WebSocket connections managed by [`api/routers/socket.py`](https://github.com/debpalash/VoiceStudio/blob/main/api/routers/socket.py) to push JSON progress payloads. Clients connect to `/ws/progress/{job_id}` endpoints to receive real-time updates containing `job_id`, `progress` percentage, and `chunk_id` without HTTP polling overhead.

### Can clients cancel an in-progress audiobook generation job?

Yes, clients can trigger cancellation through the job management API, which updates the job status in [`api/routers/job_store.py`](https://github.com/debpalash/VoiceStudio/blob/main/api/routers/job_store.py) to `cancelled`. The `_ChunkedGenerator` checks this status between chunks and terminates gracefully, while `_publish_progress` broadcasts a final cancellation event to all connected WebSocket clients.

### What distinguishes the audiobook router from the longform router in VoiceStudio?

As implemented in `debpalash/VoiceStudio`, the **audiobook router** ([`api/routers/audiobook.py`](https://github.com/debpalash/VoiceStudio/blob/main/api/routers/audiobook.py)) uses larger chunk sizes optimized for complete file downloads, while the **longform router** ([`api/routers/longform.py`](https://github.com/debpalash/VoiceStudio/blob/main/api/routers/longform.py)) configures smaller segments to enable streaming-while-processing behavior. Both routers share the same `_run_engine` interface and WebSocket broadcasting infrastructure but adjust buffering parameters to match their respective use cases.