A non-official ElevenLabs voice synthesis RESTful client for the Unity Game Engine.
Based on ElevenLabs-DotNet
I am not affiliated with ElevenLabs and an account with api access is required.
All copyrights, trademarks, logos, and assets are the property of their respective owners.
Requires Unity 2021.3 LTS or higher.
The recommended installation method is though the unity package manager and OpenUPM.
- Open your Unity project settings
- Select the
Package Manager
- Add the OpenUPM package registry:
- Name:
OpenUPM
- URL:
https://package.openupm.com
- Scope(s):
com.rest.elevenlabs
com.utilities
- Name:
- Open the Unity Package Manager window
- Change the Registry from Unity to
My Registries
- Add the
ElevenLabs
package
- Open your Unity Package Manager
- Add package from git url:
https://github.com/RageAgainstThePixel/com.rest.elevenlabs.git#upm
Note: this repo has dependencies on other repositories! You are responsible for adding these on your own.
- Authentication
- API Proxy
- Editor Dashboard
- Text to Speech
- Voices
- Dubbing 🆕
- SFX Generation 🆕
- History
- User
There are 4 ways to provide your API keys, in order of precedence:
- Pass keys directly with constructor
⚠️ - Unity Scriptable Object
⚠️ - Load key from configuration file
- Use System Environment Variables
var api = new ElevenLabsClient("yourApiKey");
Or create a ElevenLabsAuthentication
object manually
var api = new ElevenLabsClient(new ElevenLabsAuthentication("yourApiKey"));
You can save the key directly into a scriptable object that is located in the Assets/Resources
folder.
You can create a new one by using the context menu of the project pane and creating a new ElevenLabsConfiguration
scriptable object.
Attempts to load api keys from a configuration file, by default .elevenlabs
in the current directory, optionally traversing up the directory tree or in the user's home directory.
To create a configuration file, create a new text file named .elevenlabs
and containing the line:
{
"apiKey": "yourApiKey",
}
You can also load the file directly with known path by calling a static method in Authentication:
var api = new ElevenLabsClient(new ElevenLabsAuthentication().LoadFromDirectory("your/path/to/.elevenlabs"));;
Use your system's environment variables specify an api key to use.
- Use
ELEVEN_LABS_API_KEY
for your api key.
var api = new ElevenLabsClient(new ElevenLabsAuthentication().LoadFromEnvironment());
Using either the ElevenLabs-DotNet or com.rest.elevenlabs packages directly in your front-end app may expose your API keys and other sensitive information. To mitigate this risk, it is recommended to set up an intermediate API that makes requests to ElevenLabs on behalf of your front-end app. This library can be utilized for both front-end and intermediary host configurations, ensuring secure communication with the ElevenLabs API.
In the front end example, you will need to securely authenticate your users using your preferred OAuth provider. Once the user is authenticated, exchange your custom auth token with your API key on the backend.
Follow these steps:
- Setup a new project using either the ElevenLabs-DotNet or com.rest.elevenlabs packages.
- Authenticate users with your OAuth provider.
- After successful authentication, create a new
ElevenLabsAuthentication
object and pass in the custom token. - Create a new
ElevenLabsSettings
object and specify the domain where your intermediate API is located. - Pass your new
auth
andsettings
objects to theElevenLabsClient
constructor when you create the client instance.
Here's an example of how to set up the front end:
var authToken = await LoginAsync();
var auth = new ElevenLabsAuthentication(authToken);
var settings = new ElevenLabsSettings(domain: "api.your-custom-domain.com");
var api = new ElevenLabsClient(auth, settings);
This setup allows your front end application to securely communicate with your backend that will be using the ElevenLabs-DotNet-Proxy, which then forwards requests to the ElevenLabs API. This ensures that your ElevenLabs API keys and other sensitive information remain secure throughout the process.
In this example, we demonstrate how to set up and use ElevenLabsProxyStartup
in a new ASP.NET Core web app. The proxy server will handle authentication and forward requests to the ElevenLabs API, ensuring that your API keys and other sensitive information remain secure.
- Create a new ASP.NET Core minimal web API project.
- Add the ElevenLabs-DotNet nuget package to your project.
- Powershell install:
Install-Package ElevenLabs-DotNet-Proxy
- Dotnet install:
dotnet add package ElevenLabs-DotNet-Proxy
- Manually editing .csproj:
<PackageReference Include="ElevenLabs-DotNet-Proxy" />
- Powershell install:
- Create a new class that inherits from
AbstractAuthenticationFilter
and override theValidateAuthenticationAsync
method. This will implement theIAuthenticationFilter
that you will use to check user session token against your internal server. - In
Program.cs
, create a new proxy web application by callingElevenLabsProxyStartup.CreateDefaultHost
method, passing your customAuthenticationFilter
as a type argument. - Create
ElevenLabsAuthentication
andElevenLabsClientSettings
as you would normally with your API keys, org id, or Azure settings.
public partial class Program
{
private class AuthenticationFilter : AbstractAuthenticationFilter
{
public override async Task ValidateAuthenticationAsync(IHeaderDictionary request)
{
await Task.CompletedTask; // remote resource call
// You will need to implement your own class to properly test
// custom issued tokens you've setup for your end users.
if (!request["xi-api-key"].ToString().Contains(TestUserToken))
{
throw new AuthenticationException("User is not authorized");
}
}
}
public static void Main(string[] args)
{
var client = new ElevenLabsClient();
var proxy = ElevenLabsProxyStartup.CreateDefaultHost<AuthenticationFilter>(args, client);
proxy.Run();
}
}
Once you have set up your proxy server, your end users can now make authenticated requests to your proxy api instead of directly to the ElevenLabs API. The proxy server will handle authentication and forward requests to the ElevenLabs API, ensuring that your API keys and other sensitive information remain secure.
You can perform all of the same actions from the ElevenLabs website, in the Editor using the ElevenLabs Dashboard!
Window/Dashboards/ElevenLabs
Just like in the ElevenLabs website, you can synthesize new audio clips using available voices. This tool makes it even more handy as the clips are automatically downloaded and imported into your project, ready for you to use!
Just like in the ElevenLabs website, you can manage all your voices directly in the editor.
Selecting Create New Voice
will display a popup where you can design entirely new voices using ElevenLabs generative models.
Additionally, you're also able to clone a voice from sample recordings.
You also have access to the full list of all your generated samples, ready for download.
Convert text to speech.
var api = new ElevenLabsClient();
var text = "The quick brown fox jumps over the lazy dog.";
var voice = (await api.VoicesEndpoint.GetAllVoicesAsync()).FirstOrDefault();
var defaultVoiceSettings = await api.VoicesEndpoint.GetDefaultVoiceSettingsAsync();
var voiceClip = await api.TextToSpeechEndpoint.TextToSpeechAsync(text, voice, defaultVoiceSettings);
audioSource.PlayOneShot(voiceClip.AudioClip);
Note: if you want to save the voice clip into your project, you will need to copy it from the cached path into the specified location in your project:
voiceClip.CopyIntoProject(editorDownloadDirectory);
Stream text to speech.
var api = new ElevenLabsClient();
var text = "The quick brown fox jumps over the lazy dog.";
var voice = (await api.VoicesEndpoint.GetAllVoicesAsync()).FirstOrDefault();
var partialClips = new Queue<AudioClip>();
var voiceClip = await api.TextToSpeechEndpoint.StreamTextToSpeechAsync(
text,
voice,
partialClip =>
{
// Note: Best to queue them and play them in update loop!
// See TextToSpeech sample demo for details
partialClips.Enqueue(partialClip);
});
// The full completed clip:
audioSource.clip = voiceClip.AudioClip;
Access to voices created either by the user or ElevenLabs.
Gets a list of shared voices in the public voice library.
var api = new ElevenLabsClient();
var results = await ElevenLabsClient.SharedVoicesEndpoint.GetSharedVoicesAsync();
foreach (var voice in results.Voices)
{
Debug.Log($"{voice.OwnerId} | {voice.VoiceId} | {voice.Date} | {voice.Name}");
}
Gets a list of all available voices.
var api = new ElevenLabsClient();
var allVoices = await api.VoicesEndpoint.GetAllVoicesAsync();
foreach (var voice in allVoices)
{
Debug.Log($"{voice.Id} | {voice.Name} | similarity boost: {voice.Settings?.SimilarityBoost} | stability: {voice.Settings?.Stability}");
}
Gets the global default voice settings.
var api = new ElevenLabsClient();
var result = await api.VoicesEndpoint.GetDefaultVoiceSettingsAsync();
Debug.Log($"stability: {result.Stability} | similarity boost: {result.SimilarityBoost}");
var api = new ElevenLabsClient();
var voice = await api.VoicesEndpoint.GetVoiceAsync("voiceId");
Debug.Log($"{voice.Id} | {voice.Name} | {voice.PreviewUrl}");
Edit the settings for a specific voice.
var api = new ElevenLabsClient();
var success = await api.VoicesEndpoint.EditVoiceSettingsAsync(voice, new VoiceSettings(0.7f, 0.7f));
Debug.Log($"Was successful? {success}");
var api = new ElevenLabsClient();
var labels = new Dictionary<string, string>
{
{ "accent", "american" }
};
var audioSamplePaths = new List<string>();
var voice = await api.VoicesEndpoint.AddVoiceAsync("Voice Name", audioSamplePaths, labels);
var api = new ElevenLabsClient();
var labels = new Dictionary<string, string>
{
{ "age", "young" }
};
var audioSamplePaths = new List<string>();
var success = await api.VoicesEndpoint.EditVoiceAsync(voice, audioSamplePaths, labels);
Debug.Log($"Was successful? {success}");
var api = new ElevenLabsClient();
var success = await api.VoicesEndpoint.DeleteVoiceAsync(voiceId);
Debug.Log($"Was successful? {success}");
Access to your samples, created by you when cloning voices.
var api = new ElevenLabsClient();
var voiceClip = await api.VoicesEndpoint.DownloadVoiceSampleAsync(voice, sample);
var api = new ElevenLabsClient();
var success = await api.VoicesEndpoint.DeleteVoiceSampleAsync(voiceId, sampleId);
Debug.Log($"Was successful? {success}");
Dubs provided audio or video file into given language.
var api = new ElevenLabsClient();
// from URI
var request = new DubbingRequest(new Uri("https://youtu.be/Zo5-rhYOlNk"), "ja", "en", 1, true);
// from file
var request = new DubbingRequest(filePath, "es", "en", 1);
var metadata = await api.DubbingEndpoint.DubAsync(request, progress: new Progress<DubbingProjectMetadata>(metadata =>
{
switch (metadata.Status)
{
case "dubbing":
Debug.Log($"Dubbing for {metadata.DubbingId} in progress... Expected Duration: {metadata.ExpectedDurationSeconds:0.00} seconds");
break;
case "dubbed":
Debug.Log($"Dubbing for {metadata.DubbingId} complete in {metadata.TimeCompleted.TotalSeconds:0.00} seconds!");
break;
default:
Debug.Log($"Status: {metadata.Status}");
break;
}
}));
Returns metadata about a dubbing project, including whether it’s still in progress or not.
var api = new ElevenLabsClient();
var metadata = api.await GetDubbingProjectMetadataAsync("dubbing-id");
Returns downloaded dubbed file path.
Important
Videos will be returned in MP4 format and audio only dubs will be returned in MP3.
var dubbedClipPath = await ElevenLabsClient.DubbingEndpoint.GetDubbedFileAsync(metadata.DubbingId, request.TargetLanguage);
var dubbedClip = await Rest.DownloadAudioClipAsync($"file://{dubbedClipPath}", AudioType.MPEG);
audioSource.PlayOneShot(dubbedClip);
Returns transcript for the dub in the desired format.
var srcFile = new FileInfo(audioPath);
var transcriptPath = new FileInfo($"{srcFile.FullName}.dubbed.{request.TargetLanguage}.srt");
var transcriptFile = await ElevenLabsClient.DubbingEndpoint.GetTranscriptForDubAsync(metadata.DubbingId, request.TargetLanguage);
await File.WriteAllTextAsync(transcriptPath.FullName, transcriptFile);
Deletes a dubbing project.
var api = new ElevenLabsClient();
await api.DubbingEndpoint.DeleteDubbingProjectAsync("dubbing-id");
API that converts text into sounds & uses the most advanced AI audio model ever.
var api = new ElevenLabsClient();
var request = new SoundGenerationRequest("Star Wars Light Saber parry");
var clip = await api.SoundGenerationEndpoint.GenerateSoundAsync(request);
Access to your previously synthesized audio clips including its metadata.
Get metadata about all your generated audio.
var api = new ElevenLabsClient();
var historyItems = await api.HistoryEndpoint.GetHistoryAsync();
foreach (var item in historyItems.OrderBy(historyItem => historyItem.Date))
{
Debug.Log($"{item.State} {item.Date} | {item.Id} | {item.Text.Length} | {item.Text}");
}
Get information about a specific item.
var api = new ElevenLabsClient();
var historyItem = await api.HistoryEndpoint.GetHistoryItemAsync(voiceClip.Id);
var api = new ElevenLabsClient();
var voiceClip = await api.HistoryEndpoint.DownloadHistoryAudioAsync(historyItem);
Downloads the last 100 history items, or the collection of specified items.
var api = new ElevenLabsClient();
var voiceClips = await api.HistoryEndpoint.DownloadHistoryItemsAsync();
Note: to copy the clips directly into your project you can additionally call:
VoiceClipUtilities.CopyIntoProject(editorDownloadDirectory, downloadItems.ToArray());
var api = new ElevenLabsClient();
var success = await api.HistoryEndpoint.DeleteHistoryItemAsync(historyItem);
Debug.Log($"Was successful? {success}");
Access to your user Information and subscription status.
Gets information about your user account with ElevenLabs.
var api = new ElevenLabsClient();
var userInfo = await api.UserEndpoint.GetUserInfoAsync();
Gets information about your subscription with ElevenLabs.
var api = new ElevenLabsClient();
var subscriptionInfo = await api.UserEndpoint.GetSubscriptionInfoAsync();