EVI .NET Quickstart

A quickstart guide for integrating the Empathic Voice Interface (EVI) with .NET.

In this guide, you’ll learn how to use Hume’s .NET SDK to integrate with EVI.

Make sure that connecting to EVI from your .NET code is the right choice.

If your .NET app is a client app — a desktop application or CLI that runs on the user’s machine and captures audio directly from their microphone — then connecting to EVI from .NET is appropriate.

If your .NET app is a server app that will not run on the same machine to which the user’s microphone is connected, it is usually better to connect to EVI not from .NET code but directly from the client to keep latency low. If you need to control an EVI chat with logic that MUST live on your backend, and have your .NET backend use the Send Message endpoint or Control Plane WebSocket connection to control an EVI chat that was already opened from the client.

The example code in this guide sends EVI hardcoded audio from a file, as a placeholder. You should replace this with logic that sends audio sourced from your user’s microphone.

  1. Environment setup: Download package and system dependencies to run EVI.
  2. Import statements: Import needed symbols from the Hume SDK.
  3. Authentication: Use your API credentials to authenticate your EVI application.
  4. Connection: Set up a secure WebSocket connection to interact with EVI.
  5. Handling incoming messages: Subscribe to events and process messages from EVI.
  6. Audio input: Capture audio data from an input device and send to EVI.

Environment setup

Create a new .NET project and install the required packages:

dotnet new console -n EviDotnetQuickstart
cd EviDotnetQuickstart
dotnet add package Hume
dotnet add package DotNetEnv

Download sample audio

Download the sample PCM audio file to use with this guide:

curl -O https://raw.githubusercontent.com/HumeAI/hume-api-examples/main/evi/evi-dotnet-quickstart/sample_input.pcm

Import statements

First, import the needed namespaces from the .NET standard library and the Hume SDK.

Program.cs
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using DotNetEnv;
using Hume;
using Hume.EmpathicVoice;

Authentication

Log into your Hume AI Account and obtain an API key. Create a .env file in your project directory and store your API key:

.env
HUME_API_KEY=your_api_key_here

Load the environment variables and use the API key to instantiate the HumeClient class. This is the main entry point provided by the Hume .NET SDK.

Program.cs
Env.Load();
var apiKey = Environment.GetEnvironmentVariable("HUME_API_KEY")
?? throw new InvalidOperationException("HUME_API_KEY environment variable is required.");
var client = new HumeClient(apiKey);

Connection

To connect to an EVI chat, create a ChatApi instance using the client.EmpathicVoice.CreateChatApi method. You can specify session settings in the ChatApi.Options object.

Program.cs
// Create a signal to wait for Chat Metadata
var chatMetadataReceived = new TaskCompletionSource<bool>();
// Create the ChatApi instance
var chatApi = client.EmpathicVoice.CreateChatApi(new ChatApi.Options
{
ApiKey = apiKey,
SessionSettings = new ConnectSessionSettings(),
});

Connect to EVI and wait for the chat metadata to confirm the connection is established:

Program.cs
// Connect to EVI
Console.WriteLine("Connecting to EVI...");
await chatApi.ConnectAsync();
Console.WriteLine("Connected!");
// Wait for Chat Metadata
Console.WriteLine("Waiting for Chat Metadata...");
await chatMetadataReceived.Task;
Console.WriteLine("Chat Metadata received.");

Handling incoming messages

EVI communicates through events. Subscribe to the events you want to handle before connecting. The main event types are:

  • AssistantMessage: Text messages from EVI
  • UserMessage: Transcriptions of user speech
  • AudioOutput: Audio data for playback
  • ChatMetadata: Information about the chat session
Program.cs
// Subscribe to events
chatApi.AssistantMessage.Subscribe(message =>
{
Console.WriteLine($"Assistant: {message.Message?.Content}");
});
chatApi.UserMessage.Subscribe(message =>
{
Console.WriteLine($"User: {message.Message?.Content}");
});
chatApi.AudioOutput.Subscribe(audio =>
{
Console.WriteLine($"Received audio chunk: {audio.Data?.Length ?? 0} bytes");
});
chatApi.ChatMetadata.Subscribe(metadata =>
{
Console.WriteLine($"Chat Metadata - Chat ID: {metadata.ChatId}");
chatMetadataReceived.TrySetResult(true);
});

Audio input

Before sending audio, configure the audio format by sending session settings. EVI expects audio in a specific format (e.g., 48kHz, 16-bit, mono PCM).

Program.cs
// Configure audio format (48kHz, 16-bit, mono PCM)
const int sampleRate = 48000;
const int channels = 1;
var sessionSettings = new SessionSettings
{
Audio = new AudioConfiguration
{
Encoding = "linear16",
SampleRate = sampleRate,
Channels = channels
}
};
await chatApi.Send(sessionSettings);

Sending audio data

Audio data should be sent as base64-encoded chunks. Here’s a helper function that reads a PCM file and streams it to EVI in real-time chunks:

Program.cs
static async Task TransmitTestAudio(ChatApi chatApi, string filePath, int sampleRate, int channels)
{
const int chunkDurationMs = 10;
const int bytesPerSample = 2; // 16-bit audio
int bytesPerChunk = sampleRate * bytesPerSample * channels * chunkDurationMs / 1000;
// Read PCM file
var audioData = File.ReadAllBytes(filePath);
// Split into chunks and send with appropriate timing
for (int offset = 0; offset < audioData.Length; offset += bytesPerChunk)
{
var chunkSize = Math.Min(bytesPerChunk, audioData.Length - offset);
var chunk = audioData.Skip(offset).Take(chunkSize).ToArray();
// Pad final chunk if needed
if (chunk.Length < bytesPerChunk)
{
chunk = chunk.Concat(new byte[bytesPerChunk - chunk.Length]).ToArray();
}
// Send as base64-encoded audio input
var data = Convert.ToBase64String(chunk);
await chatApi.Send(new AudioInput { Data = data });
// Delay to simulate real-time streaming
await Task.Delay(chunkDurationMs);
}
}

Put it all together

Here’s the complete example that connects to EVI and transmits audio:

Program.cs
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using DotNetEnv;
using Hume;
using Hume.EmpathicVoice;
Env.Load();
var apiKey = Environment.GetEnvironmentVariable("HUME_API_KEY")
?? throw new InvalidOperationException("HUME_API_KEY environment variable is required.");
var client = new HumeClient(apiKey);
// Create a signal to wait for Chat Metadata
var chatMetadataReceived = new TaskCompletionSource<bool>();
// Create the ChatApi instance
var chatApi = client.EmpathicVoice.CreateChatApi(new ChatApi.Options
{
ApiKey = apiKey,
SessionSettings = new ConnectSessionSettings(),
});
// Subscribe to events
chatApi.AssistantMessage.Subscribe(message =>
{
Console.WriteLine($"Assistant: {message.Message?.Content}");
});
chatApi.UserMessage.Subscribe(message =>
{
Console.WriteLine($"User: {message.Message?.Content}");
});
chatApi.AudioOutput.Subscribe(audio =>
{
Console.WriteLine($"Received audio chunk: {audio.Data?.Length ?? 0} bytes");
});
chatApi.ChatMetadata.Subscribe(metadata =>
{
Console.WriteLine($"Chat Metadata - Chat ID: {metadata.ChatId}");
chatMetadataReceived.TrySetResult(true);
});
// Connect to EVI
Console.WriteLine("Connecting to EVI...");
await chatApi.ConnectAsync();
Console.WriteLine("Connected!");
// Wait for Chat Metadata
await chatMetadataReceived.Task;
// Configure audio format (48kHz, 16-bit, mono PCM)
const int sampleRate = 48000;
const int channels = 1;
var sessionSettings = new SessionSettings
{
Audio = new AudioConfiguration
{
Encoding = "linear16",
SampleRate = sampleRate,
Channels = channels
}
};
await chatApi.Send(sessionSettings);
// Send audio (replace with your audio source)
// await TransmitTestAudio(chatApi, "sample_input.pcm", sampleRate, channels);
// Wait for responses
await Task.Delay(5000);
await chatApi.DisposeAsync();

Running the example

dotnet run

View the complete example code on GitHub.

Next steps

Next, consider exploring these areas to enhance your EVI application:

For further details and practical examples, explore the API Reference and our Hume API Examples on GitHub.