vibevoice-asr
README.md
# VibeVoice-ASR Server
Local speech-to-text using Microsoft's [VibeVoice-ASR](https://huggingface.co/microsoft/VibeVoice-ASR-HF) model. Run it as an **OpenAI-compatible API server** or as an **MCP server** that plugs directly into Claude Code, OpenCode, Cursor, and other AI tools.
- Automatic speaker diarization
- Timestamps on every segment
- Output as plain text, JSON, SRT, or VTT
- Runs on CUDA, Apple Silicon (MPS), or CPU
- Model downloads automatically on first run
## Requirements
- Python 3.10+
- [FFmpeg](https://ffmpeg.org/) (used by the model's audio processor)
**Install FFmpeg:**
```bash
# macOS
brew install ffmpeg
# Ubuntu / Debian
sudo apt-get install ffmpeg
# Windows (with Chocolatey)
choco install ffmpeg
```
## Quick Start
```bash
# Clone the repo
git clone https://github.com/tjameswilliams/vibevoice-server.git
cd vibevoice-server
# Create a virtual environment (recommended)
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# Install
pip install -e .
# For NVIDIA GPU acceleration (optional)
pip install -e ".[cuda]"
```
The first time you run either the API server or MCP server, the model (~3 GB) will be downloaded from HuggingFace and cached locally.
---
## Option 1: OpenAI-Compatible API Server
Start the server:
```bash
vibevoice-server
```
The server starts on `http://localhost:8000` by default. It exposes the same endpoint shape as the OpenAI Audio API, so any client library or tool that speaks that protocol works out of the box.
### CLI Options
```
vibevoice-server [OPTIONS]
--host Bind address (default: 0.0.0.0)
--port Bind port (default: 8000)
--device Device: auto, cuda, mps, cpu (default: auto)
--dtype Data type: auto, bfloat16, float32 (default: auto)
--log-level Log level: debug, info, warning, error (default: info)
```
### Transcribe Audio
```bash
curl http://localhost:8000/v1/audio/transcriptions \
-F file=@meeting.wav \
-F response_format=verbose_json
```
**Parameters:**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `file` | file | required | Audio file (wav, mp3, flac, m4a, ogg, etc.) |
| `model` | string | `vibevoice-asr` | Model identifier (accepted but ignored) |
| `response_format` | string | `json` | `text`, `json`, `verbose_json`, `srt`, `vtt` |
| `prompt` | string | | Optional context to guide transcription |
| `language` | string | | Language code (used in verbose_json output) |
### Response Formats
**`json`** (default):
```json
{"text": "Hello, welcome to the meeting."}
```
**`verbose_json`** — includes timestamps, speaker IDs, and segments:
```json
{
"task": "transcribe",
"language": "en",
"duration": 12.5,
"text": "Hello, welcome to the meeting.",
"segments": [
{"id": 0, "start": 0.0, "end": 3.2, "text": "Hello, welcome to the meeting.", "speaker": 0}
]
}
```
**`srt`** and **`vtt`** — subtitle formats with speaker labels, ready to use with video players.
**`text`** — plain transcript string, no JSON wrapper.
### Other Endpoints
```bash
# List models
curl http://localhost:8000/v1/models
# Health check
curl http://localhost:8000/health
```
### Using with OpenAI Client Libraries
Point any OpenAI SDK at your local server:
```python
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="not-needed")
with open("recording.wav", "rb") as f:
transcript = client.audio.transcriptions.create(
model="vibevoice-asr",
file=f,
response_format="verbose_json",
)
print(transcript.text)
```
### Docker
```bash
# Build
docker build -t vibevoice-server .
# Run (CPU)
docker run -p 8000:8000 -v vibevoice-cache:/models vibevoice-server
# Run (NVIDIA GPU)
docker run --gpus all -p 8000:8000 -v vibevoice-cache:/models vibevoice-server
```
---
## Option 2: MCP Server
The MCP (Model Context Protocol) server lets AI tools call transcription directly — no HTTP server needed. The model runs in the same process as the MCP server.
### MCP Tools
| Tool | Description |
|------|-------------|
| `transcribe_audio` | Transcribe an audio file. Pass an absolute file path and get back the transcript. |
| `load_vibevoice_model` | Pre-load the model into memory (~60-90s). Optional — the model loads automatically on first transcription. |
| `get_vibevoice_status` | Check whether the model is loaded, and which device/dtype it's using. |
**`transcribe_audio` parameters:**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `file_path` | string | required | Absolute path to the audio file |
| `response_format` | string | `text` | `text`, `json`, `verbose_json`, `srt`, `vtt` |
| `prompt` | string | | Optional context to guide transcription |
| `language` | string | | Language code (for verbose_json output) |
### Claude Code
Add to your project's `.mcp.json` (or `~/.claude/mcp.json` for global access):
```json
{
"mcpServers": {
"vibevoice-asr": {
"command": "vibevoice-mcp",
"args": []
}
}
}
```
With device override:
```json
{
"mcpServers": {
"vibevoice-asr": {
"command": "vibevoice-mcp",
"args": ["--device", "mps"]
}
}
}
```
Restart Claude Code after adding the config. The three tools (`transcribe_audio`, `load_vibevoice_model`, `get_vibevoice_status`) will appear automatically.
### Cursor
Add to `.cursor/mcp.json` in your project root:
```json
{
"mcpServers": {
"vibevoice-asr": {
"command": "vibevoice-mcp",
"args": []
}
}
}
```
### OpenCode
Add to your OpenCode MCP configuration (`opencode.json` or via settings):
```json
{
"mcpServers": {
"vibevoice-asr": {
"command": "vibevoice-mcp",
"args": []
}
}
}
```
### Any MCP-Compatible Tool
The server uses **stdio transport** — the standard for local MCP servers. Any tool that supports MCP can run it with:
- **Command:** `vibevoice-mcp`
- **Args:** `[]` (optional: `["--device", "mps"]` or `["--device", "cuda"]`)
- **Transport:** stdio
The MCP server reads JSON-RPC from stdin and writes responses to stdout. All logs go to stderr.
### MCP CLI Options
```
vibevoice-mcp [OPTIONS]
--device Device: auto, cuda, mps, cpu (default: auto)
--dtype Data type: auto, bfloat16, float32 (default: auto)
--log-level Log level (default: warning)
```
---
## Configuration
All settings can be controlled via environment variables (prefixed with `VIBEVOICE_`), CLI flags, or a `.env` file. See `.env.example` for the full list.
| Variable | Default | Description |
|----------|---------|-------------|
| `VIBEVOICE_DEVICE` | `auto` | `auto`, `cuda`, `mps`, `cpu` |
| `VIBEVOICE_DTYPE` | `auto` | `auto`, `bfloat16`, `float32` |
| `VIBEVOICE_CACHE_DIR` | (HuggingFace default) | Where to store downloaded model weights |
| `VIBEVOICE_MODEL_ID` | `microsoft/VibeVoice-ASR-HF` | HuggingFace model ID |
| `VIBEVOICE_HOST` | `0.0.0.0` | API server bind address |
| `VIBEVOICE_PORT` | `8000` | API server bind port |
| `VIBEVOICE_LOG_LEVEL` | `info` | Logging level |
**Device auto-detection** picks the best available: CUDA > MPS > CPU.
---
## Hardware Notes
| Platform | Device | Dtype | Notes |
|----------|--------|-------|-------|
| NVIDIA GPU | `cuda` | `bfloat16` | Fastest. Flash Attention 2 enabled automatically. Install with `.[cuda]`. |
| Apple Silicon | `mps` | `float32` | Works well on M1/M2/M3/M4. |
| CPU | `cpu` | `float32` | Slower but works everywhere. |
The model is ~3 GB. First load takes 60-90 seconds (downloading + loading weights). Subsequent starts are faster when cached.
---
## License
MIT
TDQS
A4.1/5.0
Scored across 3 tools
Disambiguation5/5
Each tool has a unique purpose: checking server status, loading the model, and transcribing audio. No functional overlap, making it clear which tool to use for each task.
Naming Consistency5/5
All tool names follow a consistent verb_noun pattern in snake_case (get_vibevoice_status, load_vibevoice_model, transcribe_audio), making them predictable and easy to remember.
Tool Count5/5
Three tools cover the essential operations of an ASR server—status check, model loading, and transcription. The count is well-scoped for the domain without unnecessary extras.
Completeness4/5
The set covers the core workflow (status, load, transcribe). A minor gap is the lack of an unload model tool, but this does not severely hinder functionality for typical use cases.