elbruno/ElBruno.VibeVoiceTTS

C#

15

105 commits

updated Jul 3, 2026

See the code

README

πŸŽ™οΈ VibeVoiceTTS

NuGet NuGet Downloads Build Status License: MIT HuggingFace GitHub stars Twitter Follow

A .NET library for text-to-speech synthesis using Microsoft's VibeVoice-Realtime-0.5B β€” native C# inference via ONNX Runtime, no Python required at runtime.

Features

  • πŸ”Š Natural Text-to-Speech β€” High-quality speech synthesis powered by VibeVoice-Realtime-0.5B
  • πŸ“¦ NuGet Package β€” ElBruno.VibeVoiceTTS β€” install and start generating speech in minutes
  • πŸ€– Pure C# Inference β€” ONNX Runtime, zero Python dependency at runtime
  • πŸš€ GPU Acceleration β€” DirectML (any Windows GPU) and CUDA (NVIDIA) support with automatic CPU fallback
  • πŸ“₯ Auto-Download β€” Models automatically downloaded from πŸ€— HuggingFace on first use
  • πŸ“‘ Streaming Chunks API β€” ordered PCM chunk delivery through GenerateAudioStreamingAsync()
  • 🌍 6 Voice Presets β€” Carter, Davis, Emma, Frank, Grace, Mike (English voices with multilingual experimental support)
  • πŸ’‰ Dependency Injection β€” First-class IServiceCollection integration
  • πŸ–₯️ Cross-Platform β€” Windows, Linux, macOS, MAUI-ready

Installation

dotnet add package ElBruno.VibeVoiceTTS

Quick Start

1) Generate speech and save to WAV

using ElBruno.VibeVoiceTTS;

using var tts = new VibeVoiceSynthesizer();
await tts.EnsureModelAvailableAsync(); // auto-downloads ~1.5 GB on first run

float[] audio = await tts.GenerateAudioAsync("Hello! Welcome to VibeVoiceTTS.", "Carter");
tts.SaveWav("output.wav", audio);

2) Use voice presets

// Use the enum (recommended)
float[] carter = await tts.GenerateAudioAsync("Hello from Carter!", VibeVoicePreset.Carter);
float[] emma = await tts.GenerateAudioAsync("Hello from Emma!", VibeVoicePreset.Emma);

// Or use a string name β€” both short and internal names work
float[] audio = await tts.GenerateAudioAsync("Hello!", "Carter");
float[] audio2 = await tts.GenerateAudioAsync("Hello!", "en-Carter_man"); // also works

3) Discover available voices

// Voices currently downloaded on disk
string[] available = tts.GetAvailableVoices();
// β†’ ["Carter", "Emma"]  (default download includes Carter and Emma)

// All supported voices (including those not yet downloaded)
string[] supported = tts.GetSupportedVoices();
// β†’ ["Carter", "Davis", "Emma", "Frank", "Grace", "Mike"]

// Detailed metadata for all supported voices
VoiceInfo[] details = tts.GetSupportedVoiceDetails();
foreach (var voice in details)
    Console.WriteLine($"{voice.Name} ({voice.Gender}, {voice.Language})");

πŸ’‘ On-demand voice download: Only Carter and Emma are downloaded by default with EnsureModelAvailableAsync(). Other voices (Davis, Frank, Grace, Mike) are automatically downloaded on first use when you call GenerateAudioAsync(). You can also pre-download a specific voice:

await tts.EnsureVoiceAvailableAsync("Davis", progress);

4) Track download progress

var progress = new Progress<DownloadProgress>(p =>
{
    if (p.Stage == DownloadStage.Downloading)
        Console.Write($"\r⬇️ [{p.CurrentFile}] {p.PercentComplete:F0}%");
    else
        Console.WriteLine($"{p.Stage}: {p.Message}");
});

await tts.EnsureModelAvailableAsync(progress);

5) Configure options

var options = new VibeVoiceOptions
{
    ModelPath = @"D:\models\vibevoice",  // Custom model location (default: OS cache)
    DiffusionSteps = 20,                 // Quality vs speed tradeoff
    CfgScale = 1.5f,                     // Classifier-free guidance scale
    SampleRate = 24000,                  // Output sample rate
    MaxTextLength = 500,                 // Max characters per request (0 disables the limit)
};

using var tts = new VibeVoiceSynthesizer(options);

6) Stream ordered PCM chunks

await foreach (var chunk in tts.GenerateAudioStreamingAsync(
    "Streaming-ready chunk delivery without a second full-audio copy.",
    VibeVoicePreset.Carter))
{
    Console.WriteLine(
        $"Chunk #{chunk.SequenceNumber} | Samples: {chunk.Samples.Length} | Final: {chunk.IsFinal}");
}

Console.WriteLine(tts.StreamingCapabilities);
// -> { SupportsProgressiveGeneration = false, SupportsChunkedDelivery = true }

πŸ’‘ Streaming behavior: The current ONNX pipeline finishes waveform generation before chunk emission starts, so SupportsProgressiveGeneration is false. Chunks are then exposed in-order from the generated PCM buffer, so SupportsChunkedDelivery is true.

OptionDefaultDescription
ModelPathOS cache*Directory where ONNX models are stored and downloaded
HuggingFaceRepoelbruno/VibeVoice-Realtime-0.5B-ONNXHuggingFace repo for model downloads
DiffusionSteps20Number of diffusion denoising steps
CfgScale1.5Classifier-free guidance scale
SampleRate24000Output audio sample rate (Hz)
MaxTextLength500Maximum characters accepted per request (0 disables validation)
Seed42Random seed for reproducible output
ExecutionProviderCpuONNX Runtime execution provider (Cpu, DirectML, Cuda)
GpuDeviceId0GPU device index (used with DirectML or CUDA)

*Default model cache: Windows: %LOCALAPPDATA%\ElBruno\VibeVoice\models Β· Linux/macOS: ~/.local/share/elbruno/vibevoice/models

7) GPU Acceleration

Enable GPU acceleration by setting the execution provider and installing the corresponding NuGet package:

# For DirectML (any Windows GPU β€” NVIDIA, AMD, Intel):
dotnet add package Microsoft.ML.OnnxRuntime.DirectML

# For CUDA (NVIDIA only β€” Windows and Linux):
dotnet add package Microsoft.ML.OnnxRuntime.Gpu
// DirectML β€” recommended for Windows desktop apps
var options = new VibeVoiceOptions
{
    ExecutionProvider = ExecutionProvider.DirectML,
    GpuDeviceId = 0   // optional, selects which GPU
};
using var tts = new VibeVoiceSynthesizer(options);

// CUDA β€” for NVIDIA GPUs with CUDA drivers
var options = new VibeVoiceOptions
{
    ExecutionProvider = ExecutionProvider.Cuda,
    GpuDeviceId = 0
};
using var tts = new VibeVoiceSynthesizer(options);

πŸ’‘ Note: If the selected GPU provider is unavailable (missing NuGet package or no compatible GPU), the library automatically falls back to CPU inference. When using DirectML, models with dynamic tensor shapes (LM models, acoustic decoder) run on CPU while fixed-shape models (prediction head, connector, EOS classifier) use GPU β€” this works around known DirectML limitations with dynamic Reshape and ConvTranspose operations.

8) Dependency Injection

builder.Services.AddVibeVoice(options =>
{
    options.DiffusionSteps = 20;
});

// Then inject IVibeVoiceSynthesizer in your services

9) Microsoft.Extensions.AI ITextToSpeechClient

using ElBruno.VibeVoiceTTS.Extensions;
using Microsoft.Extensions.AI;

builder.Services.AddVibeVoice(
    configure: options =>
    {
        options.SampleRate = 24000;
    },
    configureTextToSpeech: options =>
    {
        options.DefaultAudioFormat = VibeVoiceTextToSpeechOptions.WavMediaType;
    });

var client = app.Services.GetRequiredService<ITextToSpeechClient>();

TextToSpeechResponse response = await client.GetAudioAsync(
    "Hello from Microsoft.Extensions.AI!",
    new TextToSpeechOptions
    {
        VoiceId = "Emma",
        AudioFormat = "audio/pcm;format=s16le"
    });

var audio = response.Contents.OfType<DataContent>().Single();
Console.WriteLine(audio.MediaType);
// -> audio/pcm;rate=24000;channels=1;format=s16le

Supported adapter output types:

  • audio/wav
  • audio/pcm;rate=24000;channels=1;format=f32le
  • audio/pcm;rate=24000;channels=1;format=s16le

GetService(typeof(TextToSpeechClientMetadata)) returns provider metadata, TextToSpeechOptions.VoiceId maps to the existing VibeVoice voice presets/internal names, and AdditionalProperties["sampleRate"] is validated against the synthesizer's configured sample rate.

10) Cancellation, metrics, streaming, and concurrent use

using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));

tts.GenerationMetricReported += (_, metric) =>
{
    Console.WriteLine($"{metric.Stage}: {metric.Elapsed.TotalMilliseconds:F0} ms ({metric.FramesGenerated} frames)");
};

float[] audio = await tts.GenerateAudioAsync(
    "This request can be cancelled while queued or during generation.",
    "Carter",
    cts.Token);

πŸ’‘ Concurrency behavior: A single VibeVoiceSynthesizer instance serializes GenerateAudioAsync() and EnsureVoiceAvailableAsync() calls so the shared ONNX pipeline cannot be mutated mid-request. If a caller is waiting for that capacity, cancelling its CancellationToken aborts the wait. Create multiple synthesizer instances if you need true parallel generation.

πŸ’‘ Metrics behavior: GenerationMetricReported emits FirstAudioReady when the first latent audio frame is ready and Completed when the final waveform has been decoded.

πŸ’‘ Streaming behavior: GenerateAudioStreamingAsync() uses the same cancellation rules. If cancellation happens while enumerating chunks, no further audio chunks are emitted and exactly one yielded chunk is marked IsFinal = true.

πŸ’‘ Tip: For best results, keep sentences short (~10 words). Longer text may produce artifacts due to model limitations. Consider splitting long text into sentences. πŸ’‘ Tip: The MaxTextLength option defaults to 500 characters. Raise it for long passages, or set it to 0 to disable the guard entirely.

πŸ—£οΈ Voices & Languages

VoiceGenderPreset EnumInternal Name
CarterMaleVibeVoicePreset.Carteren-Carter_man
DavisMaleVibeVoicePreset.Davisen-Davis_man
EmmaFemaleVibeVoicePreset.Emmaen-Emma_woman
FrankMaleVibeVoicePreset.Franken-Frank_man
GraceFemaleVibeVoicePreset.Graceen-Grace_woman
MikeMaleVibeVoicePreset.Mikeen-Mike_man

All 6 voice presets are available on HuggingFace and are downloaded on-demand when first used.

⚑ Migration note: In versions prior to 0.2.0, GetAvailableVoices() returned all 6 voices regardless of download status. Starting with 0.2.0, it returns only voices actually downloaded on disk. Use GetSupportedVoices() to see all 6 known presets. Voices are auto-downloaded on first use with GenerateAudioAsync(), or pre-download with EnsureVoiceAvailableAsync("Davis").

Language support: The model is primarily trained on English, with experimental multilingual capabilities (e.g., Spanish, French, German). Results may vary for non-English text.

πŸ“– For full details on the model, supported languages, and voice characteristics, see the official VibeVoice documentation on HuggingFace and the VibeVoice GitHub repository.

For the complete API reference and advanced usage, see the Getting Started Guide.

Scenarios

This repository includes example projects demonstrating different ways to use VibeVoice:

#StatusScenarioStackLevelDescription
1βœ…Simple Python ScriptPythonBeginnerMinimal TTS demo β€” useful for model export and testing
2βœ…Full-Stack AppPython + Blazor + AspireIntermediateWeb app with FastAPI backend and Blazor frontend
3βœ…C# Console AppC# (.NET 8)BeginnerRecommended starting point β€” pure C# with ElBruno.VibeVoiceTTS
4βœ…Full C# with AspireC# + Blazor + AspireIntermediateFull-stack C# app with WebAPI + Blazor frontend
5βœ…Batch ProcessingPythonIntermediateCLI to convert folders of .txt to .wav
6βœ…Real-Time StreamingPythonIntermediateChunked audio playback for low-latency
7βœ…MAUI MobileC# (.NET 10 MAUI)AdvancedCross-platform app with in-process ONNX TTS via ElBruno.VibeVoiceTTS NuGet package
8βœ…ONNX ExportPython β†’ C#AdvancedONNX model export tools and pipeline docs

Note: Python scenarios (1, 2, 5, 6) are primarily for ONNX model export, testing, and reference. The C# scenarios (3, 4) run entirely in .NET with no Python dependency. See the Scenarios Guide for details.

ONNX Models on HuggingFace

Pre-exported ONNX models are available on HuggingFace β€” the C# library downloads them automatically:

πŸ€— elbruno/VibeVoice-Realtime-0.5B-ONNX

The model includes 9 ONNX files (autoregressive pipeline with KV-cache) and 6 voice presets. See Scenario 8 for export details.

Documentation

TopicDescription
Getting StartedPrerequisites, setup, and first steps
Scenarios GuideDetailed descriptions of all 8 scenarios
ArchitectureSystem design, ONNX pipeline, and data flow
Project StructureRepository layout and file organization
API ReferenceREST API documentation (for web scenarios)
User ManualEnd-user guide for web interfaces
PublishingNuGet publishing with GitHub Actions

Tech Stack

LayerTechnologyPurpose
C# TTS LibraryElBruno.VibeVoiceTTSReusable .NET library with HuggingFace auto-download
TTS ModelVibeVoice-Realtime-0.5BMicrosoft's text-to-speech model
InferenceONNX RuntimeNative C# model inference
FrontendBlazor (.NET 10)Interactive web UI
Orchestration.NET AspireService discovery & health checks

Building from Source

git clone https://github.com/elbruno/ElBruno.VibeVoiceTTS.git
cd ElBruno.VibeVoiceTTS
dotnet build src/ElBruno.VibeVoiceTTS/ElBruno.VibeVoiceTTS.csproj
dotnet test src/ElBruno.VibeVoiceTTS.Tests/ElBruno.VibeVoiceTTS.Tests.csproj

Requirements

  • .NET 8.0 SDK or later
  • ONNX Runtime compatible platform (Windows, Linux, macOS)
  • Python 3.11+ (only needed for ONNX model export β€” not for runtime use)

🀝 Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

πŸ“„ License

This project is licensed under the MIT License β€” see the LICENSE file for details.

πŸ‘‹ About the Author

Hi! I'm ElBruno 🧑, a passionate developer and content creator exploring AI, .NET, and modern development practices.

Made with ❀️ by ElBruno

If you like this project, consider following my work across platforms:

  • πŸ“» Podcast: No Tienen Nombre β€” Spanish-language episodes on AI, development, and tech culture
  • πŸ’» Blog: ElBruno.com β€” Deep dives on embeddings, RAG, .NET, and local AI
  • πŸ“Ί YouTube: youtube.com/elbruno β€” Demos, tutorials, and live coding
  • πŸ”— LinkedIn: @elbruno β€” Professional updates and insights
  • 𝕏 Twitter: @elbruno β€” Quick tips, releases, and tech news
ai
blazor
csharp
directml
dotnet
dotnet-aspire
gpu-acceleration
huggingface
machine-learning
maui
microsoft
nuget
onnx
onnx-runtime
speech-synthesis
text-to-speech
tts
vibevoice

Contributors

elbruno

100 commits

Copilot

3 commits

Claude

1 commits

vasireddy

1 commits

elbruno/ElBruno.VibeVoiceTTS

C#

15

105 commits

updated Jul 3, 2026

See the code

README

πŸŽ™οΈ VibeVoiceTTS

NuGet NuGet Downloads Build Status License: MIT HuggingFace GitHub stars Twitter Follow

A .NET library for text-to-speech synthesis using Microsoft's VibeVoice-Realtime-0.5B β€” native C# inference via ONNX Runtime, no Python required at runtime.

Features

  • πŸ”Š Natural Text-to-Speech β€” High-quality speech synthesis powered by VibeVoice-Realtime-0.5B
  • πŸ“¦ NuGet Package β€” ElBruno.VibeVoiceTTS β€” install and start generating speech in minutes
  • πŸ€– Pure C# Inference β€” ONNX Runtime, zero Python dependency at runtime
  • πŸš€ GPU Acceleration β€” DirectML (any Windows GPU) and CUDA (NVIDIA) support with automatic CPU fallback
  • πŸ“₯ Auto-Download β€” Models automatically downloaded from πŸ€— HuggingFace on first use
  • πŸ“‘ Streaming Chunks API β€” ordered PCM chunk delivery through GenerateAudioStreamingAsync()
  • 🌍 6 Voice Presets β€” Carter, Davis, Emma, Frank, Grace, Mike (English voices with multilingual experimental support)
  • πŸ’‰ Dependency Injection β€” First-class IServiceCollection integration
  • πŸ–₯️ Cross-Platform β€” Windows, Linux, macOS, MAUI-ready

Installation

dotnet add package ElBruno.VibeVoiceTTS

Quick Start

1) Generate speech and save to WAV

using ElBruno.VibeVoiceTTS;

using var tts = new VibeVoiceSynthesizer();
await tts.EnsureModelAvailableAsync(); // auto-downloads ~1.5 GB on first run

float[] audio = await tts.GenerateAudioAsync("Hello! Welcome to VibeVoiceTTS.", "Carter");
tts.SaveWav("output.wav", audio);

2) Use voice presets

// Use the enum (recommended)
float[] carter = await tts.GenerateAudioAsync("Hello from Carter!", VibeVoicePreset.Carter);
float[] emma = await tts.GenerateAudioAsync("Hello from Emma!", VibeVoicePreset.Emma);

// Or use a string name β€” both short and internal names work
float[] audio = await tts.GenerateAudioAsync("Hello!", "Carter");
float[] audio2 = await tts.GenerateAudioAsync("Hello!", "en-Carter_man"); // also works

3) Discover available voices

// Voices currently downloaded on disk
string[] available = tts.GetAvailableVoices();
// β†’ ["Carter", "Emma"]  (default download includes Carter and Emma)

// All supported voices (including those not yet downloaded)
string[] supported = tts.GetSupportedVoices();
// β†’ ["Carter", "Davis", "Emma", "Frank", "Grace", "Mike"]

// Detailed metadata for all supported voices
VoiceInfo[] details = tts.GetSupportedVoiceDetails();
foreach (var voice in details)
    Console.WriteLine($"{voice.Name} ({voice.Gender}, {voice.Language})");

πŸ’‘ On-demand voice download: Only Carter and Emma are downloaded by default with EnsureModelAvailableAsync(). Other voices (Davis, Frank, Grace, Mike) are automatically downloaded on first use when you call GenerateAudioAsync(). You can also pre-download a specific voice:

await tts.EnsureVoiceAvailableAsync("Davis", progress);

4) Track download progress

var progress = new Progress<DownloadProgress>(p =>
{
    if (p.Stage == DownloadStage.Downloading)
        Console.Write($"\r⬇️ [{p.CurrentFile}] {p.PercentComplete:F0}%");
    else
        Console.WriteLine($"{p.Stage}: {p.Message}");
});

await tts.EnsureModelAvailableAsync(progress);

5) Configure options

var options = new VibeVoiceOptions
{
    ModelPath = @"D:\models\vibevoice",  // Custom model location (default: OS cache)
    DiffusionSteps = 20,                 // Quality vs speed tradeoff
    CfgScale = 1.5f,                     // Classifier-free guidance scale
    SampleRate = 24000,                  // Output sample rate
    MaxTextLength = 500,                 // Max characters per request (0 disables the limit)
};

using var tts = new VibeVoiceSynthesizer(options);

6) Stream ordered PCM chunks

await foreach (var chunk in tts.GenerateAudioStreamingAsync(
    "Streaming-ready chunk delivery without a second full-audio copy.",
    VibeVoicePreset.Carter))
{
    Console.WriteLine(
        $"Chunk #{chunk.SequenceNumber} | Samples: {chunk.Samples.Length} | Final: {chunk.IsFinal}");
}

Console.WriteLine(tts.StreamingCapabilities);
// -> { SupportsProgressiveGeneration = false, SupportsChunkedDelivery = true }

πŸ’‘ Streaming behavior: The current ONNX pipeline finishes waveform generation before chunk emission starts, so SupportsProgressiveGeneration is false. Chunks are then exposed in-order from the generated PCM buffer, so SupportsChunkedDelivery is true.

OptionDefaultDescription
ModelPathOS cache*Directory where ONNX models are stored and downloaded
HuggingFaceRepoelbruno/VibeVoice-Realtime-0.5B-ONNXHuggingFace repo for model downloads
DiffusionSteps20Number of diffusion denoising steps
CfgScale1.5Classifier-free guidance scale
SampleRate24000Output audio sample rate (Hz)
MaxTextLength500Maximum characters accepted per request (0 disables validation)
Seed42Random seed for reproducible output
ExecutionProviderCpuONNX Runtime execution provider (Cpu, DirectML, Cuda)
GpuDeviceId0GPU device index (used with DirectML or CUDA)

*Default model cache: Windows: %LOCALAPPDATA%\ElBruno\VibeVoice\models Β· Linux/macOS: ~/.local/share/elbruno/vibevoice/models

7) GPU Acceleration

Enable GPU acceleration by setting the execution provider and installing the corresponding NuGet package:

# For DirectML (any Windows GPU β€” NVIDIA, AMD, Intel):
dotnet add package Microsoft.ML.OnnxRuntime.DirectML

# For CUDA (NVIDIA only β€” Windows and Linux):
dotnet add package Microsoft.ML.OnnxRuntime.Gpu
// DirectML β€” recommended for Windows desktop apps
var options = new VibeVoiceOptions
{
    ExecutionProvider = ExecutionProvider.DirectML,
    GpuDeviceId = 0   // optional, selects which GPU
};
using var tts = new VibeVoiceSynthesizer(options);

// CUDA β€” for NVIDIA GPUs with CUDA drivers
var options = new VibeVoiceOptions
{
    ExecutionProvider = ExecutionProvider.Cuda,
    GpuDeviceId = 0
};
using var tts = new VibeVoiceSynthesizer(options);

πŸ’‘ Note: If the selected GPU provider is unavailable (missing NuGet package or no compatible GPU), the library automatically falls back to CPU inference. When using DirectML, models with dynamic tensor shapes (LM models, acoustic decoder) run on CPU while fixed-shape models (prediction head, connector, EOS classifier) use GPU β€” this works around known DirectML limitations with dynamic Reshape and ConvTranspose operations.

8) Dependency Injection

builder.Services.AddVibeVoice(options =>
{
    options.DiffusionSteps = 20;
});

// Then inject IVibeVoiceSynthesizer in your services

9) Microsoft.Extensions.AI ITextToSpeechClient

using ElBruno.VibeVoiceTTS.Extensions;
using Microsoft.Extensions.AI;

builder.Services.AddVibeVoice(
    configure: options =>
    {
        options.SampleRate = 24000;
    },
    configureTextToSpeech: options =>
    {
        options.DefaultAudioFormat = VibeVoiceTextToSpeechOptions.WavMediaType;
    });

var client = app.Services.GetRequiredService<ITextToSpeechClient>();

TextToSpeechResponse response = await client.GetAudioAsync(
    "Hello from Microsoft.Extensions.AI!",
    new TextToSpeechOptions
    {
        VoiceId = "Emma",
        AudioFormat = "audio/pcm;format=s16le"
    });

var audio = response.Contents.OfType<DataContent>().Single();
Console.WriteLine(audio.MediaType);
// -> audio/pcm;rate=24000;channels=1;format=s16le

Supported adapter output types:

  • audio/wav
  • audio/pcm;rate=24000;channels=1;format=f32le
  • audio/pcm;rate=24000;channels=1;format=s16le

GetService(typeof(TextToSpeechClientMetadata)) returns provider metadata, TextToSpeechOptions.VoiceId maps to the existing VibeVoice voice presets/internal names, and AdditionalProperties["sampleRate"] is validated against the synthesizer's configured sample rate.

10) Cancellation, metrics, streaming, and concurrent use

using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));

tts.GenerationMetricReported += (_, metric) =>
{
    Console.WriteLine($"{metric.Stage}: {metric.Elapsed.TotalMilliseconds:F0} ms ({metric.FramesGenerated} frames)");
};

float[] audio = await tts.GenerateAudioAsync(
    "This request can be cancelled while queued or during generation.",
    "Carter",
    cts.Token);

πŸ’‘ Concurrency behavior: A single VibeVoiceSynthesizer instance serializes GenerateAudioAsync() and EnsureVoiceAvailableAsync() calls so the shared ONNX pipeline cannot be mutated mid-request. If a caller is waiting for that capacity, cancelling its CancellationToken aborts the wait. Create multiple synthesizer instances if you need true parallel generation.

πŸ’‘ Metrics behavior: GenerationMetricReported emits FirstAudioReady when the first latent audio frame is ready and Completed when the final waveform has been decoded.

πŸ’‘ Streaming behavior: GenerateAudioStreamingAsync() uses the same cancellation rules. If cancellation happens while enumerating chunks, no further audio chunks are emitted and exactly one yielded chunk is marked IsFinal = true.

πŸ’‘ Tip: For best results, keep sentences short (~10 words). Longer text may produce artifacts due to model limitations. Consider splitting long text into sentences. πŸ’‘ Tip: The MaxTextLength option defaults to 500 characters. Raise it for long passages, or set it to 0 to disable the guard entirely.

πŸ—£οΈ Voices & Languages

VoiceGenderPreset EnumInternal Name
CarterMaleVibeVoicePreset.Carteren-Carter_man
DavisMaleVibeVoicePreset.Davisen-Davis_man
EmmaFemaleVibeVoicePreset.Emmaen-Emma_woman
FrankMaleVibeVoicePreset.Franken-Frank_man
GraceFemaleVibeVoicePreset.Graceen-Grace_woman
MikeMaleVibeVoicePreset.Mikeen-Mike_man

All 6 voice presets are available on HuggingFace and are downloaded on-demand when first used.

⚑ Migration note: In versions prior to 0.2.0, GetAvailableVoices() returned all 6 voices regardless of download status. Starting with 0.2.0, it returns only voices actually downloaded on disk. Use GetSupportedVoices() to see all 6 known presets. Voices are auto-downloaded on first use with GenerateAudioAsync(), or pre-download with EnsureVoiceAvailableAsync("Davis").

Language support: The model is primarily trained on English, with experimental multilingual capabilities (e.g., Spanish, French, German). Results may vary for non-English text.

πŸ“– For full details on the model, supported languages, and voice characteristics, see the official VibeVoice documentation on HuggingFace and the VibeVoice GitHub repository.

For the complete API reference and advanced usage, see the Getting Started Guide.

Scenarios

This repository includes example projects demonstrating different ways to use VibeVoice:

#StatusScenarioStackLevelDescription
1βœ…Simple Python ScriptPythonBeginnerMinimal TTS demo β€” useful for model export and testing
2βœ…Full-Stack AppPython + Blazor + AspireIntermediateWeb app with FastAPI backend and Blazor frontend
3βœ…C# Console AppC# (.NET 8)BeginnerRecommended starting point β€” pure C# with ElBruno.VibeVoiceTTS
4βœ…Full C# with AspireC# + Blazor + AspireIntermediateFull-stack C# app with WebAPI + Blazor frontend
5βœ…Batch ProcessingPythonIntermediateCLI to convert folders of .txt to .wav
6βœ…Real-Time StreamingPythonIntermediateChunked audio playback for low-latency
7βœ…MAUI MobileC# (.NET 10 MAUI)AdvancedCross-platform app with in-process ONNX TTS via ElBruno.VibeVoiceTTS NuGet package
8βœ…ONNX ExportPython β†’ C#AdvancedONNX model export tools and pipeline docs

Note: Python scenarios (1, 2, 5, 6) are primarily for ONNX model export, testing, and reference. The C# scenarios (3, 4) run entirely in .NET with no Python dependency. See the Scenarios Guide for details.

ONNX Models on HuggingFace

Pre-exported ONNX models are available on HuggingFace β€” the C# library downloads them automatically:

πŸ€— elbruno/VibeVoice-Realtime-0.5B-ONNX

The model includes 9 ONNX files (autoregressive pipeline with KV-cache) and 6 voice presets. See Scenario 8 for export details.

Documentation

TopicDescription
Getting StartedPrerequisites, setup, and first steps
Scenarios GuideDetailed descriptions of all 8 scenarios
ArchitectureSystem design, ONNX pipeline, and data flow
Project StructureRepository layout and file organization
API ReferenceREST API documentation (for web scenarios)
User ManualEnd-user guide for web interfaces
PublishingNuGet publishing with GitHub Actions

Tech Stack

LayerTechnologyPurpose
C# TTS LibraryElBruno.VibeVoiceTTSReusable .NET library with HuggingFace auto-download
TTS ModelVibeVoice-Realtime-0.5BMicrosoft's text-to-speech model
InferenceONNX RuntimeNative C# model inference
FrontendBlazor (.NET 10)Interactive web UI
Orchestration.NET AspireService discovery & health checks

Building from Source

git clone https://github.com/elbruno/ElBruno.VibeVoiceTTS.git
cd ElBruno.VibeVoiceTTS
dotnet build src/ElBruno.VibeVoiceTTS/ElBruno.VibeVoiceTTS.csproj
dotnet test src/ElBruno.VibeVoiceTTS.Tests/ElBruno.VibeVoiceTTS.Tests.csproj

Requirements

  • .NET 8.0 SDK or later
  • ONNX Runtime compatible platform (Windows, Linux, macOS)
  • Python 3.11+ (only needed for ONNX model export β€” not for runtime use)

🀝 Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

πŸ“„ License

This project is licensed under the MIT License β€” see the LICENSE file for details.

πŸ‘‹ About the Author

Hi! I'm ElBruno 🧑, a passionate developer and content creator exploring AI, .NET, and modern development practices.

Made with ❀️ by ElBruno

If you like this project, consider following my work across platforms:

  • πŸ“» Podcast: No Tienen Nombre β€” Spanish-language episodes on AI, development, and tech culture
  • πŸ’» Blog: ElBruno.com β€” Deep dives on embeddings, RAG, .NET, and local AI
  • πŸ“Ί YouTube: youtube.com/elbruno β€” Demos, tutorials, and live coding
  • πŸ”— LinkedIn: @elbruno β€” Professional updates and insights
  • 𝕏 Twitter: @elbruno β€” Quick tips, releases, and tech news
ai
blazor
csharp
directml
dotnet
dotnet-aspire
gpu-acceleration
huggingface
machine-learning
maui
microsoft
nuget
onnx
onnx-runtime
speech-synthesis
text-to-speech
tts
vibevoice

Contributors

elbruno

100 commits

Copilot

3 commits

Claude

1 commits

vasireddy

1 commits

Languages

C#

56.6%

Python

27.3%

HTML

10.2%

CSS

5.0%