Speech faster than
it plays. No Python.
I wrote the whole S2-Pro inference path in C and CUDA — tokenizer, both transformers, the vocoder, the scheduler, the HTTP server. Nothing else is in the runtime. It synthesises at half of realtime on one DGX Spark, so a sentence is audible before you finish reading it.
$ docker pull ghcr.io/luka-loehr/s2pro-native:1.0.1 $ docker run --gpus all -p 8010:8010 \ -v s2pro-data:/data \ ghcr.io/luka-loehr/s2pro-native:1.0.1
Sixteen measured steps, each gated on layer parity, MD5 bit-exactness or a listening test. The ones that lost are written down too — FP8 failed parity and stayed only as a memory-system probe.
One DGX Spark (GB10, sm_121), single stream, streamed over HTTP, temperature 0.8, top-p 0.8, fixed seed. RTF is compute ÷ audio, so below 1.0 means synthesis outruns playback.
Let your agent set it up
You were going to paste it into Claude anyway. I saved you the typing. It fetches the runbook, checks you actually have a Spark, pulls the image, waits out the checkpoint download and proves the server works with a real wav.
Set me up with s2pro-native — Fish Audio S2-Pro serving in native C and CUDA
on a DGX Spark. Run this first, then follow it exactly, top to bottom:
curl -fsSL https://s2pro.lukaloehr.com/setup.txt
Ask me its first question before doing anything else. Never print my tokens.Two commands
Ah, so you haven’t fallen for the vibe yet. Respect. I still read commands before I run them too.
Pull and run
Needs a DGX Spark (GB10, sm_121) with Docker and the NVIDIA runtime. The host needs no CUDA toolkit, no Python, no PyTorch. On first start the entrypoint downloads the S2-Pro checkpoint into the volume and converts the codec; every later start is warm.
$ docker pull ghcr.io/luka-loehr/s2pro-native:1.0.1 $ docker run --gpus all -p 8010:8010 \ -v s2pro-data:/data ghcr.io/luka-loehr/s2pro-native:1.0.1
The checkpoint is under the Fish Audio Research License and is never baked into the image. Set HF_TOKEN if the repo asks for one, and S2P_TOKEN for bearer auth.
Ask it to say something
/v1/tts streams a WAV header and then S16LE frames as they are generated. Pass voice to pick a registry voice, or reference_audio_b64 plus reference_text to clone one (15 s max).
$ curl -X POST localhost:8010/v1/tts \
-d '{"text":"Hello from a DGX Spark.","format":"wav"}' -o hello.wavThe server binds loopback and does not terminate TLS. Put it behind an authenticated proxy before exposing it, and read SECURITY.md first.
Measured on one Spark
Serving
Runtime
HTTP API
GET /healthzengine + scheduler statsGET /v1/voicesnamed-voice registryPOST /v1/ttsstreaming synthesis (WAV or PCM)8010