Sign inSign up

eworkerinc/vibevoice

By eworkerinc

Updated about 1 year ago

Image
Machine learning & AI
7

3.4K

eworkerinc/vibevoice repository overview

E‑Worker VibeVoice Integration Stack (GPU)

Overview

The E‑Worker VibeVoice Integration Stack (GPU) is a unified, single‑container deployment that exposes a clean HTTP proxy on one public port while keeping Microsoft’s VibeVoice backends private inside. This stack simplifies setup, enforces security, and enables applications—including E‑Worker Soundstage—to integrate seamlessly with high‑quality text‑to‑speech (TTS).

https://app.eworker.ca

https://www.reddit.com/r/eworker_ca/

https://x.com/eworker_ca

Important: The VibeVoice API are ready to use, the E-Worker Soundstage UI is still under development.



What’s Included

  • Public port 8745 with X-API-Key authentication.
  • Private, internal model servers (1.5B and Large).
  • Prebaked tags embed model weights for faster startup.
  • Built‑in CORS for browser‑based apps.
  • Optional HTTPS via built‑in Caddy with ACME.

System Requirements

  • GPU: NVIDIA with drivers + NVIDIA Container Toolkit.

  • Base: CUDA 12.4 (NGC PyTorch).

  • Driver: 550+ recommended.

  • Architectures: Turing, Ampere, Ada (RTX 20/30/40, A10, L4). Volta (V100) may work.

  • VRAM (approx.):

    • 1.5B → 10–12 GB.
    • Large → 20–24 GB.
    • Both models enabled concurrently → ~30–36 GB (sum of both, plus minor runtime overhead). On GPUs with ≤24 GB VRAM, prefer running a single model.
  • Disk (cache):

    • 1.5B → 10–20 GB.
    • Large → 25–40 GB.
  • Docker: 24+.

Quick GPU check:

nvidia-smi
docker run --rm --gpus all nvidia/cuda:12.4.1-base-ubuntu24.04 nvidia-smi

Installation

Pull
docker pull eworkerinc/vibevoice:latest   # alias of :full (prebaked)
Quick Start (Single Port 8745)

Persistent cache/state setup:

sudo mkdir -p /mnt/vv-hf /mnt/vv-voices /mnt/vv-state \
  && sudo chown -R "$USER":"$USER" /mnt/vv-hf /mnt/vv-voices /mnt/vv-state

Run both models:

docker run -d --name vibevoice --gpus all \
  -p 8745:8745 \
  -v /mnt/vv-hf:/root/.cache/huggingface \
  -e ENABLE_1_5B=true -e ENABLE_LARGE=true \
  -e AUTH_REQUIRED=true \
  -e CORS_ENABLED=true -e ALLOWED_ORIGINS='*' \
  -v /mnt/vv-voices:/app/voices \
  -v /mnt/vv-state:/var/lib/eworker \
  eworkerinc/vibevoice:latest

VRAM note:

  • Enabling both models loads both into GPU memory. Expect ~30–36 GB combined. If you have a 16–24 GB card, use a single model instead (see below).

Run with 1.5B only:

docker run -d --name vibevoice-1_5b --gpus all \
  -p 8745:8745 -v /mnt/vv-hf:/root/.cache/huggingface \
  -e ENABLE_1_5B=true -e ENABLE_LARGE=false \
  eworkerinc/vibevoice:latest

VRAM savings:

  • 1.5B typically fits in ~10–12 GB VRAM, saving roughly 8–12 GB compared to Large. This is the recommended mode for 12–16 GB consumer GPUs and for maximizing concurrency.

Run with Large only:

docker run -d --name vibevoice-large --gpus all \
  -p 8745:8745 -v /mnt/vv-hf:/root/.cache/huggingface \
  -e ENABLE_1_5B=false -e ENABLE_LARGE=true \
  eworkerinc/vibevoice:latest

VRAM trade‑off:

  • Large delivers higher quality at the cost of VRAM (~20–24 GB). Use this mode on 24 GB+ GPUs. Compared to running both, Large‑only reduces memory by ~10–12 GB; compared to 1.5B, it consumes ~8–12 GB more.
HTTPS with ACME (Optional)
docker run -d --name vibevoice \
  -p 80:80 -p 443:443 \
  -v /mnt/vv-hf:/root/.cache/huggingface \
  -v /mnt/vv-state:/var/lib/eworker \
  -e TLS_MODE=acme -e TLS_DOMAIN=voice.example.com -e [email protected] \
  -e AUTH_REQUIRED=true -e ENABLE_1_5B=true -e ENABLE_LARGE=true \
  eworkerinc/vibevoice:latest

Authentication & Security

  • Header: X-API-Key: <key> (printed on first run, persisted under /var/lib/eworker/api.key).
  • Rotate keys: RESET_API_KEY=true once or set API_KEY explicitly.
  • CORS: CORS_ENABLED + ALLOWED_ORIGINS.
  • HTTPS: enable ACME with TLS_MODE=acme.

Endpoints (Proxy)

  • GET /health → health probe.
  • GET /v1/voice/models → list available models.
  • GET /v1/voice/models/{model_id} → model defaults/hints.
  • GET /v1/voice/voices → list voices (supports ?model= filter).
  • GET /v1/voice/voices/{voice_id}/preview?text=... → quick WAV preview.
  • POST /v1/voice/jobs → start TTS job (returns job_id).
  • GET /v1/voice/jobs → list jobs; filter by model/status.
  • GET /v1/voice/jobs/{job_id} → job status/progress.
  • GET /v1/voice/jobs/{job_id}/result → audio result.
  • POST /v1/voice/jobs/{job_id}/cancel → cancel job.
  • GET /v1/voice/jobs/metrics → aggregated job metrics.

Samples

Health check:

curl -s http://localhost:8745/health | jq .

Get API key:

KEY=$(docker logs vibevoice 2>&1 | sed -n 's/^X-API-Key: //p' | tail -1)

List voices:

curl -s http://localhost:8745/v1/voice/voices -H "X-API-Key: $KEY" | jq
# If only Large is enabled, include the model filter:
curl -s "http://localhost:8745/v1/voice/voices?model=vibevoice-large" -H "X-API-Key: $KEY" | jq

Preview a single voice:

curl -s "http://localhost:8745/v1/voice/voices/Alice/preview?text=Hello" \
  -H "X-API-Key: $KEY" --output preview.wav

Two‑speaker dialogue (very small):

cat > body.json <<'JSON'
{
  "model": "vibevoice-1.5b",
  "script": "Speaker 1: Hello there!\nSpeaker 2: Hi! Great to meet you.",
  "speakers": [ { "voiceName": "Alice" }, { "voiceName": "Carter" } ],
  "overrides": {
    "guidance": { "inference_steps": 28, "cfg_scale": 4.5 }
  }
}
JSON

JOB_ID=$(curl -s -X POST http://localhost:8745/v1/voice/jobs \
  -H "Content-Type: application/json" -H "X-API-Key: $KEY" \
  --data-binary @body.json | jq -r .job_id)

curl -s "http://localhost:8745/v1/voice/jobs/$JOB_ID/result" -H "X-API-Key: $KEY" \
  | jq -r .audio_wav_base64 | base64 --decode > out.wav

Custom voice from external file (mounted WAV):

# 1) Place your consented voice sample WAV on the host (3–10 seconds is ideal)
#    Requirements: mono PCM, 16‑bit, 16k or 24k sample rate recommended.

# 2) Copy or move it into the mounted voices folder (host side)
cp ~/Downloads/my-voice.wav /mnt/vv-voices/

# 3) List voices (the filename without .wav becomes the voice name)
curl -s http://localhost:8745/v1/voice/voices -H "X-API-Key: $KEY" | jq

# 4) Preview the custom voice (replace MyVoice with your filename stem)
curl -s "http://localhost:8745/v1/voice/voices/MyVoice/preview?text=Hello%20from%20my%20custom%20voice" \
  -H "X-API-Key: $KEY" --output custom-preview.wav

# 5) Use it in a job
cat > job-custom.json <<'JSON'
{
  "model": "vibevoice-1.5b",
  "script": "Speaker 1: This is my custom narrator.",
  "speakers": [ { "voiceName": "MyVoice" } ],
  "overrides": { "guidance": { "inference_steps": 24, "cfg_scale": 4.2 } }
}
JSON
JOB_ID=$(curl -s -X POST http://localhost:8745/v1/voice/jobs \
  -H "Content-Type: application/json" -H "X-API-Key: $KEY" \
  --data-binary @job-custom.json | jq -r .job_id)
curl -s "http://localhost:8745/v1/voice/jobs/$JOB_ID/result" -H "X-API-Key: $KEY" \
  | jq -r .audio_wav_base64 | base64 --decode > custom-out.wav

Tiny single‑speaker sample:

cat > tiny.json <<'JSON'
{
  "model": "vibevoice-1.5b",
  "script": "Speaker 1: Hello from VibeVoice.",
  "speakers": [ { "voiceName": "Alice" } ],
  "overrides": { "guidance": { "inference_steps": 20, "cfg_scale": 4.0 } }
}
JSON

JOB_ID=$(curl -s -X POST http://localhost:8745/v1/voice/jobs \
  -H "Content-Type: application/json" -H "X-API-Key: $KEY" \
  --data-binary @tiny.json | jq -r .job_id)

curl -s "http://localhost:8745/v1/voice/jobs/$JOB_ID/result" -H "X-API-Key: $KEY" \
  | jq -r .audio_wav_base64 | base64 --decode > tiny.wav

Tiny two‑speaker sample:

cat > tiny2.json <<'JSON'
{
  "model": "vibevoice-1.5b",
  "script": "Speaker 1: Good morning!\nSpeaker 2: Morning—ready to start?",
  "speakers": [ { "voiceName": "Mary" }, { "voiceName": "Frank" } ],
  "overrides": { "guidance": { "inference_steps": 22, "cfg_scale": 4.2 } }
}
JSON

JOB_ID=$(curl -s -X POST http://localhost:8745/v1/voice/jobs \
  -H "Content-Type: application/json" -H "X-API-Key: $KEY" \
  --data-binary @tiny2.json | jq -r .job_id)

curl -s "http://localhost:8745/v1/voice/jobs/$JOB_ID/result" -H "X-API-Key: $KEY" \
  | jq -r .audio_wav_base64 | base64 --decode > tiny2.wav

Four‑speaker English (~1–2 minutes):

cat > roundtable_en.json <<'JSON'
{
  "model": "vibevoice-1.5b",
  "script": "Speaker 1: Welcome everyone to our quick roundtable.\nSpeaker 2: Thanks—let's share highlights from this week.\nSpeaker 3: I experimented with new prompt flows and got cleaner outputs.\nSpeaker 4: Nice. I focused on latency and shaved a few seconds off.\nSpeaker 1: Did the new sampler help with stability?\nSpeaker 2: Yes, especially around tricky words and punctuation.\nSpeaker 3: I also tried a different CFG scale for warmer tone.\nSpeaker 4: And fewer inference steps were fine for short clips.\nSpeaker 1: What about longer narrations?\nSpeaker 2: We should raise steps slightly to keep quality.\nSpeaker 3: Agreed—thirty two felt like a sweet spot.\nSpeaker 4: We could A/B test with audience feedback.\nSpeaker 1: Let's line up a small user study next week.\nSpeaker 2: I can prepare scripts and scenarios.\nSpeaker 3: I will track timing and perceived naturalness.\nSpeaker 4: I'll measure CPU and GPU utilization.\nSpeaker 1: Great. Any blockers we should address?\nSpeaker 2: None on my side.\nSpeaker 3: All good here.\nSpeaker 4: Same—excited to ship improvements.\nSpeaker 1: Perfect—thanks everyone for the quick sync.",
  "speakers": [
    { "voiceName": "Alice" },
    { "voiceName": "Carter" },
    { "voiceName": "Frank" },
    { "voiceName": "Mary" }
  ],
  "overrides": { "guidance": { "inference_steps": 28, "cfg_scale": 4.5 } }
}
JSON

JOB_ID=$(curl -s -X POST http://localhost:8745/v1/voice/jobs \
  -H "Content-Type: application/json" -H "X-API-Key: $KEY" \
  --data-binary @roundtable_en.json | jq -r .job_id)

curl -s "http://localhost:8745/v1/voice/jobs/$JOB_ID/result" -H "X-API-Key: $KEY" \
  | jq -r .audio_wav_base64 | base64 --decode > roundtable_en.wav

English + Chinese (~1–2 minutes):

cat > bilingual.json <<'JSON'
{
  "model": "vibevoice-1.5b",
  "script": "Speaker 1: Hello and welcome to our bilingual demo.\nSpeaker 2: 大家好,欢迎来到我们的双语演示。\nSpeaker 1: We'll alternate between English and Chinese to compare styles.\nSpeaker 2: 我会用较自然的语气来朗读示例句子。\nSpeaker 1: First, a short introduction to the topic.\nSpeaker 2: 接下来,我们会用简短的段落来说明要点。\nSpeaker 1: Pay attention to clarity and pacing across languages.\nSpeaker 2: 请留意语速与停顿是否听起来自然。\nSpeaker 1: Finally, we'll wrap up with a brief summary.\nSpeaker 2: 最后,我们会做一个简短的总结。\nSpeaker 1: Thanks for listening.\nSpeaker 2: 谢谢收听。",
  "speakers": [ { "voiceName": "Alice" }, { "voiceName": "Xinran" } ],
  "overrides": { "guidance": { "inference_steps": 28, "cfg_scale": 4.5 } }
}
JSON

JOB_ID=$(curl -s -X POST http://localhost:8745/v1/voice/jobs \
  -H "Content-Type: application/json" -H "X-API-Key: $KEY" \
  --data-binary @bilingual.json | jq -r .job_id)

curl -s "http://localhost:8745/v1/voice/jobs/$JOB_ID/result" -H "X-API-Key: $KEY" \
  | jq -r .audio_wav_base64 | base64 --decode > bilingual.wav

Note on Large model:

  • To render with the Large model, set "model": "vibevoice-large" and consider "inference_steps": 40 for best quality.

Built‑in Voices

The image includes demo voices under /app/voices for quick testing. Friendly names:

  • Alice (en, woman)
  • Carter (en, man)
  • Frank (en, man)
  • Mary (en, woman, bgm)
  • Maya (en, woman)
  • Samuel (id, man)
  • Anchen (zh, man, bgm)
  • Bowen (zh, man)
  • Xinran (zh, woman)

Use any of the above in voiceName or with the preview endpoint (e.g., /v1/voice/voices/Frank/preview).


  • You can add your own voice samples by placing .wav files into the mounted voices directory on the host. The container scans /app/voices and exposes each file by its filename (without extension) as a voiceName.
  • Host mount: /mnt/vv-voices → container path /app/voices (see run commands above).
  • Recommended sample: 3–10 seconds, mono PCM 16‑bit at 16 kHz or 24 kHz. Trim silence for best results.
  • Use GET /v1/voice/voices to confirm your custom voice name, then preview via GET /v1/voice/voices/{voiceName}/preview and reference it in jobs (speakers[].voiceName).
  • Consent: Only use voice samples you have the legal right and consent to use. If the voice belongs to a third party, obtain explicit permission. You are responsible for complying with applicable laws, terms, and policies.

Note: Advanced users may directly supply absolute voice_sample_paths to the upstream API inside the container. The public proxy focuses on folder‑based voice management via /app/voices for simplicity and safety.


Environment Variables

  • Auth: AUTH_REQUIRED, API_KEY, RESET_API_KEY
  • Models: ENABLE_1_5B, ENABLE_LARGE
  • CORS: CORS_ENABLED, ALLOWED_ORIGINS
  • HF: HF_HOME, HF_HUB_ENABLE_HF_TRANSFER, HUGGING_FACE_HUB_TOKEN
  • Attention impl: VIBEVOICE_ATTN_IMPL (default sdpa per image env; app falls back to flash_attention_2 only if the env var is unset)
  • TLS: TLS_MODE, TLS_DOMAIN, TLS_EMAIL

Volumes

  • /root/.cache/huggingface → model cache (mount to persist downloads)
  • /var/lib/eworker → state (API key, job state)
  • /app/voices → voices folder (.wav files)

Prebaked Weights

The unified image optionally bakes model weights into the Hugging Face cache inside the image for faster cold starts.

  • Cache root: /root/.cache/huggingface/hub
  • Models cached:
    • /root/.cache/huggingface/hub/models--microsoft--VibeVoice-1.5B
    • /root/.cache/huggingface/hub/models--microsoft--VibeVoice-Large

Verify inside the image:

docker run --rm eworkerinc/vibevoice:latest bash -lc \
  'ls -1 /root/.cache/huggingface/hub | grep models--microsoft--VibeVoice'

Note: Baked weights reduce first-run downloads but do not change VRAM requirements; enabling both models still sums VRAM usage at runtime (~30–36 GB combined).


Tuning Tips

  • inference_steps (20–40 typical): higher improves quality.
  • cfg_scale (3.5–6.0 typical): adjust style/steadiness.
  • sample_rate_hz: 16000 or 24000.
  • Use 1.5B model if VRAM is constrained (saves ~8–12 GB vs Large).

Troubleshooting

  • GPU kernels: Default SDPA avoids kernel/driver mismatch issues.
  • VRAM: If out of memory, disable Large or reduce inference_steps/cfg_scale.
  • Disk: Mount HF cache on large disk; prune Docker caches.

Integration (E‑Worker Soundstage)

  • Base URL: http://localhost:8745
  • Header: X-API-Key: <printed-on-first-run>

Tag summary

Content type

Image

Digest

sha256:13a444c71

Size

34.5 GB

Last updated

about 1 year ago

docker pull eworkerinc/vibevoice