LivePortrait + JoyVASA (Local)¶
On-device audio-driven talking-head video generation on Apple Silicon.
Overview¶
The LivePortrait + JoyVASA provider generates talking-head videos locally without requiring a cloud API. It uses:
- LivePortrait (MIT) — portrait animation renderer
- JoyVASA (MIT) — audio-to-motion diffusion stage
- mediapipe (Apache-2.0) — face detection (commercial-clean)
The Go client connects to a Python gRPC server running the inference pipeline.
Quick Start¶
import (
"github.com/plexusone/omniavatar"
"github.com/plexusone/omniavatar-core/render"
_ "github.com/plexusone/omniavatar/providers/liveportrait-joyvasa"
)
// No API key needed
provider, _ := omniavatar.GetRenderProvider("liveportrait-joyvasa")
// Upload local audio
audioURL, _ := provider.(render.AudioUploader).UploadAudio(ctx, "narration.wav", f)
// Generate video
job, _ := provider.Generate(ctx, render.GenerateRequest{
AvatarID: "john", // avatar bundle name
AudioURL: audioURL,
})
// Wait and download
status, _ := render.Wait(ctx, provider, job.ID, 3*time.Second)
provider.Download(ctx, job.ID, outFile)
Setup¶
1. Start the Python Server¶
cd $GOPATH/src/github.com/plexusone/omniavatar-core/providers/liveportrait-joyvasa/server
# Create venv
arch -arm64 python3 -m venv .venv
source .venv/bin/activate
# Install and run
pip install -r requirements.txt
./generate_proto.sh
./run.sh
2. Create Avatar Bundles¶
Avatar bundles live in ~/.omniavatar/avatars/<name>/:
~/.omniavatar/avatars/
john/
metadata.json
idle/
idle.mp4 # neutral, mouth-closed clip
references/ # optional
front.png
metadata.json:
Options¶
Provider Options¶
| Option | Type | Description |
|---|---|---|
endpoint |
string | Unix socket path (default: /tmp/omniavatar-liveportrait-joyvasa.sock) |
provider, _ := omniavatar.GetRenderProvider("liveportrait-joyvasa",
omniavatar.WithExtension("endpoint", "unix:///custom/path.sock"),
)
Generate Request Extensions¶
| Option | Type | Description |
|---|---|---|
seed |
int64 | Random seed for deterministic output |
motion_scale |
float32 | Facial movement intensity (default: 1.0) |
job, _ := provider.Generate(ctx, render.GenerateRequest{
AvatarID: "john",
AudioURL: audioURL,
Extensions: map[string]any{
"seed": int64(42),
"motion_scale": float32(1.2),
},
})
Capabilities¶
| Capability | Supported |
|---|---|
render.Provider |
Yes |
render.AudioUploader |
Yes (local:// URLs) |
render.AvatarLister |
Yes (via ListAvatars RPC) |
Performance¶
On Apple Silicon (M-series):
| Metric | Value |
|---|---|
| Resolution | 512×512 |
| Speed | ~5 min for 13.7s output |
| Memory | ~4GB with model loaded |
The bottleneck is Conv3D and grid_sampler_3d falling back to CPU on MPS. torch 2.5+ may add native support for significant speedup.
Troubleshooting¶
Connection Refused¶
Ensure the Python server is running:
Model Loading Fails¶
The server sets PYTORCH_ENABLE_MPS_FALLBACK=1 automatically. If you see
Conv3D errors, verify this environment variable is set.
Out of Memory¶
The model requires ~4GB. Use UnloadModel when not actively rendering: