samuel-vitorino/soproPublic

A lightweight text-to-speech model with zero-shot voice cloning

AI summary: A lightweight, streaming text-to-speech model offering zero-shot voice cloning at extreme speeds on CPU.

Stars
877
Forks
35
Watchers
5
Open issues
2
Open PRs
0
Contributors
~2
Commits
17
Branches
2

PythonApache-2.0Created Dec 30, 2025Last push 6mo ago

Star history

since Jan 4, 2026
0250500750Jan 2026Mar 2026May 2026Aug 2026
877 stars as of Aug 6, 2026, tracked back to Jan 4, 2026. Historical curve reconstructed from public GitHub event archives, calibrated to the current total.

Signals and awards

derived from tracked data
  • Permissive license

    Apache-2.0

What sopro does

Sopro is an efficient text-to-speech engine running at just 135M parameters, bypassing heavy Transformers for a lean architecture based on dilated convolutions and cross-attention. It achieves an astonishing 0.05 Real-Time Factor on standard CPUs, meaning it generates audio 20 times faster than realtime. The model explicitly supports zero-shot voice cloning, requiring only 3 to 12 seconds of reference audio to mimic a speaker. It is heavily optimized for low-latency streaming applications where fast time-to-first-audio is critical.

Machine learning engineers and developers building local-first, low-latency audio applications. Requires a Python environment, though it relies on standard PyTorch without heavy external dependencies.

  • Extreme CPU efficiency: Generates audio at 0.05 RTF on standard consumer CPUs without requiring a dedicated GPU.
  • Zero-shot voice cloning: Replicates a target voice using just a 3-12 second audio sample.
  • Dilated convolutional architecture: Replaces standard Transformers with WaveNet-style convolutions for aggressive speedups.
  • Streaming output: Achieves a time-to-first-audio of just 250 milliseconds for real-time conversational agents.
  • Lightweight footprint: Operates effectively with only 135 million parameters, lowering deployment costs.

Where teams use it

Real-time AI voice agents

Developers can deploy responsive conversational bots on edge devices without GPU overhead.

Audiobook generation

Content creators can synthesize long-form audio narrations rapidly using a cloned custom voice.

Accessibility tools

Screen readers can run entirely locally on low-power hardware while sounding natural.

Video game dialog

Indie studios can generate dynamic NPC voice lines on the fly with minimal performance impact.

Getting started: pip install -U sopro

README

main branch
SoproTTSv1.5demo.mp4

Sopro TTS

Alt Text

πŸ“° News

2026.02.04 - SoproTTS v1.5 is out: more stable, faster, and smaller (135M parameters). Trained for just $100 on a single GPU, it reaches 250 ms TTFA streaming and 0.05 RTF (~20Γ— realtime) on CPU.

Sopro (from the Portuguese word for β€œbreath/blow”) is a lightweight English text-to-speech model I trained as a side project. Sopro is composed of dilated convs (Γ  la WaveNet) and lightweight cross-attention layers, instead of the common Transformer architecture. Even though Sopro is not SOTA across most voices and situations, I still think it’s a cool project made with a very low budget (trained on a single L40S GPU), and it can be improved with better data.

Some of the main features are:

  • 135M parameters
  • Streaming
  • Zero-shot voice cloning
  • 0.05 RTF on CPU (measured on an M3 base model), meaning it generates 32 seconds of audio in 1.77 seconds
  • 3-12 seconds of reference audio for voice cloning

Instructions

I only pinned the minimum dependency versions so you can install the package without having to create a separate env. However, some versions of Torch work best. For example, on my M3 CPU, torch==2.10.0 (without torchvision) achieves ~600 it/s on the AR generation.

(Optional)

conda create -n soprotts python=3.10
conda activate soprotts

From PyPI

pip install -U sopro

From the repo

git clone https://github.com/samuel-vitorino/sopro
cd sopro
pip install -e .

Examples

CLI

soprotts \
  --text "Sopro is a lightweight 135 million parameter text-to-speech model. Some of the main features are streaming, zero-shot voice cloning, and 0.05 real-time factor on the CPU." \
  --ref_audio ref.wav \
  --out out.wav

You have the expected temperature and top_p parameters, alongside:

  • --style_strength (controls the FiLM strength; increasing it can improve or reduce voice similarity; default 1.2)

Python

Non-streaming

from sopro import SoproTTS

tts = SoproTTS.from_pretrained("samuel-vitorino/sopro", device="cpu")

wav = tts.synthesize(
    "Hello! This is a non-streaming Sopro TTS example.",
    ref_audio_path="ref.wav",
)

tts.save_wav("out.wav", wav)

Streaming

import torch
from sopro import SoproTTS

tts = SoproTTS.from_pretrained("samuel-vitorino/sopro", device="cpu")

chunks = []
for chunk in tts.stream(
    "Hello! This is a streaming Sopro TTS example.",
    ref_audio_path="ref.mp3",
):
    chunks.append(chunk.cpu())

wav = torch.cat(chunks, dim=-1)
tts.save_wav("out_stream.wav", wav)

You can also precalculate the reference to reduce TTFA:

import torch
from sopro import SoproTTS

tts = SoproTTS.from_pretrained("samuel-vitorino/sopro", device="cpu")

ref = tts.prepare_reference(ref_audio_path="ref.mp3")

chunks = []
for chunk in tts.stream(
    "Hello! This is a streaming Sopro TTS example.",
    ref=ref,
):
    chunks.append(chunk.cpu())

wav = torch.cat(chunks, dim=-1)
tts.save_wav("out_stream.wav", wav)

Interactive streaming demo

Screenshot

After you install the sopro package:

pip install -r demo/requirements.txt
uvicorn demo.server:app --host 0.0.0.0 --port 8000

Or with docker:

docker build -t sopro-demo .
docker run --rm -p 8000:8000 sopro-demo

Navigate to http://localhost:8000 on your browser.


Disclaimers

  • Sopro can be inconsistent, so mess around with the parameters until you get a decent sample.
  • Voice cloning is highly dependent on mic quality, ambient noise, etc. On more OOD voices it might fail to match the voice well.
  • Prefer words instead of abbreviations and symbols. For example, β€œ1 + 2” β†’ β€œ1 plus 2”. That said, Sopro can generally read abbreviations like β€œCPU”, β€œTTS”, etc.
  • The streaming version is not bit-exact compared to the non-streaming version. For best quality, prioritize the non-streaming version.
  • If you use torchaudio to read or write audio, ffmpeg may be required. I recommend just using soundfile.
  • I will publish the training code once I have time to organize it.

Currently, generation is limited to ~32 seconds (400 frames). You can increase it, but the model generally hallucinates beyond that.

AI was used mainly for creating the web demo, organizing my messy code into this repo, ablations and brainstorming.

I would love to support more languages and continue improving the model. If you like this project, consider buying me a coffee so I can buy more compute: https://buymeacoffee.com/samuelvitorino


Training data


Acknowledgements

View on GitHub

Recent activity

commits and pull requests

Recent open issues

view all

Code frequency

additions and deletions
+4.6K-4.6KWeek of 2026-01-04: +4,622 linesWeek of 2026-01-04: -89 linesWeek of 2026-01-11: +0 linesWeek of 2026-01-11: -0 linesWeek of 2026-01-18: +0 linesWeek of 2026-01-18: -0 linesWeek of 2026-01-25: +0 linesWeek of 2026-01-25: -0 linesWeek of 2026-02-01: +3,726 linesWeek of 2026-02-01: -1,524 linesWeek of 2026-02-08: +0 linesWeek of 2026-02-08: -0 linesWeek of 2026-02-15: +0 linesWeek of 2026-02-15: -0 linesWeek of 2026-02-22: +0 linesWeek of 2026-02-22: -0 linesWeek of 2026-03-01: +0 linesWeek of 2026-03-01: -0 linesWeek of 2026-03-08: +0 linesWeek of 2026-03-08: -0 linesWeek of 2026-03-15: +0 linesWeek of 2026-03-15: -0 linesWeek of 2026-03-22: +0 linesWeek of 2026-03-22: -0 linesWeek of 2026-03-29: +0 linesWeek of 2026-03-29: -0 linesWeek of 2026-04-05: +0 linesWeek of 2026-04-05: -0 linesWeek of 2026-04-12: +0 linesWeek of 2026-04-12: -0 linesWeek of 2026-04-19: +0 linesWeek of 2026-04-19: -0 linesWeek of 2026-04-26: +0 linesWeek of 2026-04-26: -0 linesWeek of 2026-05-03: +0 linesWeek of 2026-05-03: -0 linesWeek of 2026-05-10: +0 linesWeek of 2026-05-10: -0 linesWeek of 2026-05-17: +0 linesWeek of 2026-05-17: -0 linesWeek of 2026-05-24: +0 linesWeek of 2026-05-24: -0 linesWeek of 2026-05-31: +0 linesWeek of 2026-05-31: -0 linesWeek of 2026-06-07: +0 linesWeek of 2026-06-07: -0 linesWeek of 2026-06-14: +0 linesWeek of 2026-06-14: -0 linesWeek of 2026-06-21: +0 linesWeek of 2026-06-21: -0 linesWeek of 2026-06-28: +0 linesWeek of 2026-06-28: -0 linesWeek of 2026-07-05: +0 linesWeek of 2026-07-05: -0 linesWeek of 2026-07-12: +0 linesWeek of 2026-07-12: -0 linesWeek of 2026-07-19: +0 linesWeek of 2026-07-19: -0 linesWeek of 2026-07-26: +0 linesWeek of 2026-07-26: -0 linesJan 4, 2026Jul 26, 2026
+8.3K lines added, -1.6K removed over the last year.

When work happens

weekday and hour
SunMonTueWedThuFriSat036912151821Sun 0:00 β€” 0 commitsSun 1:00 β€” 0 commitsSun 2:00 β€” 0 commitsSun 3:00 β€” 0 commitsSun 4:00 β€” 0 commitsSun 5:00 β€” 0 commitsSun 6:00 β€” 0 commitsSun 7:00 β€” 0 commitsSun 8:00 β€” 0 commitsSun 9:00 β€” 0 commitsSun 10:00 β€” 0 commitsSun 11:00 β€” 0 commitsSun 12:00 β€” 0 commitsSun 13:00 β€” 0 commitsSun 14:00 β€” 0 commitsSun 15:00 β€” 0 commitsSun 16:00 β€” 0 commitsSun 17:00 β€” 0 commitsSun 18:00 β€” 0 commitsSun 19:00 β€” 0 commitsSun 20:00 β€” 0 commitsSun 21:00 β€” 0 commitsSun 22:00 β€” 0 commitsSun 23:00 β€” 0 commitsMon 0:00 β€” 0 commitsMon 1:00 β€” 0 commitsMon 2:00 β€” 0 commitsMon 3:00 β€” 0 commitsMon 4:00 β€” 0 commitsMon 5:00 β€” 0 commitsMon 6:00 β€” 0 commitsMon 7:00 β€” 0 commitsMon 8:00 β€” 0 commitsMon 9:00 β€” 0 commitsMon 10:00 β€” 0 commitsMon 11:00 β€” 0 commitsMon 12:00 β€” 0 commitsMon 13:00 β€” 0 commitsMon 14:00 β€” 0 commitsMon 15:00 β€” 0 commitsMon 16:00 β€” 0 commitsMon 17:00 β€” 0 commitsMon 18:00 β€” 0 commitsMon 19:00 β€” 0 commitsMon 20:00 β€” 0 commitsMon 21:00 β€” 0 commitsMon 22:00 β€” 0 commitsMon 23:00 β€” 0 commitsTue 0:00 β€” 0 commitsTue 1:00 β€” 0 commitsTue 2:00 β€” 0 commitsTue 3:00 β€” 0 commitsTue 4:00 β€” 0 commitsTue 5:00 β€” 0 commitsTue 6:00 β€” 0 commitsTue 7:00 β€” 0 commitsTue 8:00 β€” 0 commitsTue 9:00 β€” 0 commitsTue 10:00 β€” 0 commitsTue 11:00 β€” 0 commitsTue 12:00 β€” 0 commitsTue 13:00 β€” 0 commitsTue 14:00 β€” 0 commitsTue 15:00 β€” 0 commitsTue 16:00 β€” 0 commitsTue 17:00 β€” 0 commitsTue 18:00 β€” 0 commitsTue 19:00 β€” 0 commitsTue 20:00 β€” 0 commitsTue 21:00 β€” 0 commitsTue 22:00 β€” 1 commitsTue 23:00 β€” 3 commitsWed 0:00 β€” 0 commitsWed 1:00 β€” 0 commitsWed 2:00 β€” 0 commitsWed 3:00 β€” 0 commitsWed 4:00 β€” 0 commitsWed 5:00 β€” 0 commitsWed 6:00 β€” 0 commitsWed 7:00 β€” 0 commitsWed 8:00 β€” 0 commitsWed 9:00 β€” 0 commitsWed 10:00 β€” 0 commitsWed 11:00 β€” 0 commitsWed 12:00 β€” 0 commitsWed 13:00 β€” 0 commitsWed 14:00 β€” 0 commitsWed 15:00 β€” 1 commitsWed 16:00 β€” 0 commitsWed 17:00 β€” 0 commitsWed 18:00 β€” 3 commitsWed 19:00 β€” 3 commitsWed 20:00 β€” 2 commitsWed 21:00 β€” 2 commitsWed 22:00 β€” 0 commitsWed 23:00 β€” 0 commitsThu 0:00 β€” 0 commitsThu 1:00 β€” 0 commitsThu 2:00 β€” 0 commitsThu 3:00 β€” 0 commitsThu 4:00 β€” 0 commitsThu 5:00 β€” 0 commitsThu 6:00 β€” 0 commitsThu 7:00 β€” 0 commitsThu 8:00 β€” 0 commitsThu 9:00 β€” 0 commitsThu 10:00 β€” 0 commitsThu 11:00 β€” 0 commitsThu 12:00 β€” 0 commitsThu 13:00 β€” 0 commitsThu 14:00 β€” 0 commitsThu 15:00 β€” 0 commitsThu 16:00 β€” 0 commitsThu 17:00 β€” 0 commitsThu 18:00 β€” 1 commitsThu 19:00 β€” 0 commitsThu 20:00 β€” 0 commitsThu 21:00 β€” 0 commitsThu 22:00 β€” 0 commitsThu 23:00 β€” 0 commitsFri 0:00 β€” 1 commitsFri 1:00 β€” 0 commitsFri 2:00 β€” 0 commitsFri 3:00 β€” 0 commitsFri 4:00 β€” 0 commitsFri 5:00 β€” 0 commitsFri 6:00 β€” 0 commitsFri 7:00 β€” 0 commitsFri 8:00 β€” 0 commitsFri 9:00 β€” 0 commitsFri 10:00 β€” 0 commitsFri 11:00 β€” 0 commitsFri 12:00 β€” 0 commitsFri 13:00 β€” 0 commitsFri 14:00 β€” 0 commitsFri 15:00 β€” 0 commitsFri 16:00 β€” 0 commitsFri 17:00 β€” 0 commitsFri 18:00 β€” 0 commitsFri 19:00 β€” 0 commitsFri 20:00 β€” 0 commitsFri 21:00 β€” 0 commitsFri 22:00 β€” 0 commitsFri 23:00 β€” 0 commitsSat 0:00 β€” 0 commitsSat 1:00 β€” 0 commitsSat 2:00 β€” 0 commitsSat 3:00 β€” 0 commitsSat 4:00 β€” 0 commitsSat 5:00 β€” 0 commitsSat 6:00 β€” 0 commitsSat 7:00 β€” 0 commitsSat 8:00 β€” 0 commitsSat 9:00 β€” 0 commitsSat 10:00 β€” 0 commitsSat 11:00 β€” 0 commitsSat 12:00 β€” 0 commitsSat 13:00 β€” 0 commitsSat 14:00 β€” 0 commitsSat 15:00 β€” 0 commitsSat 16:00 β€” 0 commitsSat 17:00 β€” 0 commitsSat 18:00 β€” 0 commitsSat 19:00 β€” 0 commitsSat 20:00 β€” 0 commitsSat 21:00 β€” 0 commitsSat 22:00 β€” 0 commitsSat 23:00 β€” 0 commits
Commit volume by weekday and hour (UTC). Larger dots mean more commits.

Who is committing

last 52 weeks
Maintainer commits11 (65%)
Community commits6 (35%)

17 commits in total over the last year.

DateListRankStars gained
Jan 9, 2026daily#17+83