DEV Community

Conrad Conklin
Conrad Conklin

Posted on AI-assisted

I Gave My Voice Agent a Face, and It Runs Entirely on My Own GPU

My voice agent sounded great and looked like nothing. It was a pulsing circle on a screen, which is fine for a prototype and a bit sad when you're showing it to someone.

I wanted a face. Today I tried OpenSpline, a tool that puts a live avatar on top of a voice agent. It has a hosted Cloud option, but I have a decent NVIDIA card sitting under my desk, so I went the self-host route. I had a talking avatar in about 15 minutes.

What I started with

  • A Windows machine running WSL2
  • An NVIDIA GPU
  • A Python voice agent that already worked
  • One portrait photo

The GPU is the one thing you can't skip. OpenSpline's self-hosted service needs an NVIDIA card on Linux or WSL2. AMD and Apple GPUs aren't supported, so check that before you start.

Step 1: Install and start the service

This was two commands:

curl -fsSL https://raw.githubusercontent.com/openspline/openspline/main/install.sh | sh
sh ~/.local/share/openspline/run.sh
Enter fullscreen mode Exit fullscreen mode

The first sets everything up and the second starts the service. The installer picks the right PyTorch build for your card, with CUDA 12.8 for Blackwell and 12.6 for older NVIDIA GPUs, so I didn't have to think about drivers and wheels.

As with anything you pipe into sh, I skimmed the script before running it, and you should too.

Then I opened http://localhost:7860, and a working demo was already there. This was the moment I knew it was worth continuing. I hadn't written a line of code, and I was already looking at a face that talked back.

Step 2: Plug it into my own agent

The demo is nice, but I wanted my agent to use it. The Python SDK was a single install:

pip install openspline
Enter fullscreen mode Exit fullscreen mode

Then this is the whole integration:

from openspline import Openspline

async with Openspline().avatar("portrait.jpg", quality="low") as avatar:
    print(avatar.viewer_url)
    await avatar.stream(agent.audio_stream(), sample_rate=24000)
Enter fullscreen mode Exit fullscreen mode

Here's what that does:

  1. It takes a still photo as the avatar's face.
  2. It lets you pick a quality level. I started on low to get the pipeline working.
  3. It takes whatever audio stream your agent produces.
  4. It prints a viewer URL. I opened it and watched my agent speak through the portrait.

There was nothing to configure, because the SDK defaults to the local service at http://localhost:7860. The only thing I checked was the sample rate. I matched it to my agent's audio output (24 kHz), and everything lined up.

What I liked

It's genuinely local. My audio and my portrait never leave my machine. There's no API key to manage and no usage meter running while I experiment. For a side project, that makes a difference.

The SDK is tiny. The core of it is one context manager and one stream() call. I didn't need a new architecture, just a few lines around the audio stream I already had.

It starts from a single photo. No 3D modeling, rigging or recording sessions. I gave it a portrait and got a speaking avatar.

There's room to grow. The docs cover things I haven't touched yet: multiple GPUs, a High quality mode, photo and video backgrounds, React and browser embeds, and connectors for OpenAI Realtime, LiveKit, Gemini Live and ElevenLabs.

Things to know before you try it

  • NVIDIA only. If you're on AMD or a Mac, the Cloud option is probably your route instead.
  • Begin with quality="low". Prove the pipeline end to end first, then turn quality up once you know it works.
  • Check your audio format. Mismatched sample rates are the most common way to make a voice pipeline sound wrong, so confirm yours before debugging anything else.

Where I'm taking it next

Now that the basics work, I want to try a custom background behind the portrait, embed the avatar in a web page, and see how it does with a longer, more natural conversation. A face changes how a voice agent feels. It stops being a tool you talk at and starts feeling like someone you talk to.

If you have an NVIDIA GPU and an agent that already talks, this is a good afternoon project, and you may finish it before the afternoon is over.

Docs: docs.openspline.dev/get-started/self-host

Top comments (0)