Giter Club home page Giter Club logo

elevenlabs-dotnet's Introduction

ElevenLabs-DotNet

Discord NuGet version (ElevenLabs-DotNet) NuGet version (ElevenLabs-DotNet-Proxy) Nuget Publish

A non-official Eleven Labs voice synthesis RESTful client.

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.

Requirements

  • This library targets .NET 8.0 and above.
  • It should work across console apps, winforms, wpf, asp.net, etc.
  • It should also work across Windows, Linux, and Mac.

Getting started

Install from NuGet

Install package ElevenLabs-DotNet from Nuget. Here's how via command line:

Install-Package ElevenLabs-DotNet
dotnet add package ElevenLabs-DotNet

Looking to use ElevenLabs in the Unity Game Engine? Check out our unity package on OpenUPM:

openupm


Documentation

Table of Contents

Authentication

There are 3 ways to provide your API keys, in order of precedence:

  1. Pass keys directly with constructor
  2. Load key from configuration file
  3. Use System Environment Variables

Pass keys directly with constructor

var api = new ElevenLabsClient("yourApiKey");

Or create a ElevenLabsAuthentication object manually

var api = new ElevenLabsClient(new ElevenLabsAuthentication("yourApiKey"));

Load key from configuration file

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:

Json format
{
  "apiKey": "yourApiKey",
}

You can also load the file directly with known path by calling a static method in Authentication:

var api = new ElevenLabsClient(ElevenLabsAuthentication.LoadFromDirectory("your/path/to/.elevenlabs"));;

Use System Environment Variables

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(ElevenLabsAuthentication.LoadFromEnv());

NuGet version (ElevenLabs-DotNet-Proxy)

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.

Front End Example

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:

  1. Setup a new project using either the ElevenLabs-DotNet or com.rest.elevenlabs packages.
  2. Authenticate users with your OAuth provider.
  3. After successful authentication, create a new ElevenLabsAuthentication object and pass in the custom token.
  4. Create a new ElevenLabsClientSettings object and specify the domain where your intermediate API is located.
  5. Pass your new auth and settings objects to the ElevenLabsClient 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 ElevenLabsClientSettings(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.

Back End Example

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.

  1. Create a new ASP.NET Core minimal web API project.
  2. 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" />
  3. Create a new class that inherits from AbstractAuthenticationFilter and override the ValidateAuthentication method. This will implement the IAuthenticationFilter that you will use to check user session token against your internal server.
  4. In Program.cs, create a new proxy web application by calling ElevenLabsProxyStartup.CreateWebApplication method, passing your custom AuthenticationFilter as a type argument.
  5. Create ElevenLabsAuthentication and ElevenLabsClientSettings 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 auth = ElevenLabsAuthentication.LoadFromEnv();
        var client = new ElevenLabsClient(auth);
        ElevenLabsProxyStartup.CreateWebApplication<AuthenticationFilter>(args, client).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.

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);
await File.WriteAllBytesAsync($"{voiceClip.Id}.mp3", voiceClip.ClipData.ToArray());

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();
string fileName = "myfile.mp3";
using var outputFileStream = File.OpenWrite(fileName);
var voiceClip = await api.TextToSpeechEndpoint.TextToSpeechAsync(text, voice,
partialClipCallback: async (partialClip) =>
{
    // Write the incoming data to the output file stream.
    // Alternatively you can play this clip data directly.
    await outputFileStream.WriteAsync(partialClip.ClipData);
});

Access to voices created either by the user or ElevenLabs.

Get Shared Voices

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)
{
    Console.WriteLine($"{voice.OwnerId} | {voice.VoiceId} | {voice.Date} | {voice.Name}");
}

Get All Voices

Gets a list of all available voices available to your account.

var api = new ElevenLabsClient();
var allVoices = await api.VoicesEndpoint.GetAllVoicesAsync();

foreach (var voice in allVoices)
{
    Console.WriteLine($"{voice.Id} | {voice.Name} | similarity boost: {voice.Settings?.SimilarityBoost} | stability: {voice.Settings?.Stability}");
}

Get Default Voice Settings

Gets the global default voice settings.

var api = new ElevenLabsClient();
var result = await api.VoicesEndpoint.GetDefaultVoiceSettingsAsync();
Console.WriteLine($"stability: {result.Stability} | similarity boost: {result.SimilarityBoost}");

Get Voice

var api = new ElevenLabsClient();
var voice = await api.VoicesEndpoint.GetVoiceAsync("voiceId");
Console.WriteLine($"{voice.Id} | {voice.Name} | {voice.PreviewUrl}");

Edit Voice Settings

Edit the settings for a specific voice.

var api = new ElevenLabsClient();
var success = await api.VoicesEndpoint.EditVoiceSettingsAsync(voice, new VoiceSettings(0.7f, 0.7f));
Console.WriteLine($"Was successful? {success}");

Add Voice

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);

Edit Voice

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);
Console.WriteLine($"Was successful? {success}");

Delete Voice

var api = new ElevenLabsClient();
var success = await api.VoicesEndpoint.DeleteVoiceAsync(voiceId);
Console.WriteLine($"Was successful? {success}");

Access to your samples, created by you when cloning voices.

Download Voice Sample
var api = new ElevenLabsClient();
var voiceClip = await api.VoicesEndpoint.DownloadVoiceSampleAsync(voice, sample);
await File.WriteAllBytesAsync($"{voiceClip.Id}.mp3", voiceClip.ClipData.ToArray());
Delete Voice Sample
var api = new ElevenLabsClient();
var success = await api.VoicesEndpoint.DeleteVoiceSampleAsync(voiceId, sampleId);
Console.WriteLine($"Was successful? {success}");

Dub

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":
            Console.WriteLine($"Dubbing for {metadata.DubbingId} in progress... Expected Duration: {metadata.ExpectedDurationSeconds:0.00} seconds");
            break;
        case "dubbed":
            Console.WriteLine($"Dubbing for {metadata.DubbingId} complete in {metadata.TimeCompleted.TotalSeconds:0.00} seconds!");
            break;
        default:
            Console.WriteLine($"Status: {metadata.Status}");
            break;
    }
}));

Get Dubbing Metadata

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");

Get Dubbed File

Returns dubbed file as a streamed file.

Note

Videos will be returned in MP4 format and audio only dubs will be returned in MP3.

var assetsDir = Path.GetFullPath("../../../Assets");
var dubbedPath = new FileInfo(Path.Combine(assetsDir, $"online.dubbed.{request.TargetLanguage}.mp4"));
{
    await using var fs = File.Open(dubbedPath.FullName, FileMode.Create);
    await foreach (var chunk in ElevenLabsClient.DubbingEndpoint.GetDubbedFileAsync(metadata.DubbingId, request.TargetLanguage))
    {
        await fs.WriteAsync(chunk);
    }
}

Get Transcript for Dub

Returns transcript for the dub in the desired format.

var assetsDir = Path.GetFullPath("../../../Assets");
var transcriptPath = new FileInfo(Path.Combine(assetsDir, $"online.dubbed.{request.TargetLanguage}.srt"));
{
    var transcriptFile = await api.DubbingEndpoint.GetTranscriptForDubAsync(metadata.DubbingId, request.TargetLanguage);
    await File.WriteAllTextAsync(transcriptPath.FullName, transcriptFile);
}

Delete Dubbing Project

Deletes a dubbing project.

var api = new ElevenLabsClient();
await api.DubbingEndpoint.DeleteDubbingProjectAsync("dubbing-id");

SFX Generation

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 History

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))
{
    Console.WriteLine($"{item.State} {item.Date} | {item.Id} | {item.Text.Length} | {item.Text}");
}

Get History Item

Get information about a specific item.

var api = new ElevenLabsClient();
var historyItem = await api.HistoryEndpoint.GetHistoryItemAsync(voiceClip.Id);

Download History Audio

var api = new ElevenLabsClient();
var voiceClip = await api.HistoryEndpoint.DownloadHistoryAudioAsync(historyItem);
await File.WriteAllBytesAsync($"{voiceClip.Id}.mp3", voiceClip.ClipData.ToArray());

Download History Items

Downloads the last 100 history items, or the collection of specified items.

var api = new ElevenLabsClient();
var voiceClips = await api.HistoryEndpoint.DownloadHistoryItemsAsync();

Delete History Item

var api = new ElevenLabsClient();
var success = await api.HistoryEndpoint.DeleteHistoryItemAsync(historyItem);
Console.WriteLine($"Was successful? {success}");

Access to your user Information and subscription status.

Get User Info

Gets information about your user account with ElevenLabs.

var api = new ElevenLabsClient();
var userInfo = await api.UserEndpoint.GetUserInfoAsync();

Get Subscription Info

Gets information about your subscription with ElevenLabs.

var api = new ElevenLabsClient();
var subscriptionInfo = await api.UserEndpoint.GetSubscriptionInfoAsync();

elevenlabs-dotnet's People

Contributors

ed-sparkes avatar is4code avatar stephenhodgson avatar vexthecollector avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

elevenlabs-dotnet's Issues

Streaming enhancements

Bug Report

Overview

Whilst the partialClipCallback is being called its not being streamed as and when the data is available, its buffering and then returning all the data at the end. The reason i believe this is because PostAsync does not support HttpCompletionOption.ResponseHeadersRead and so it defers to default HttpCompletionOptionResponseContentRead and waits until the whole content is available.

If you change PostAsync to SendAsync you can specify the HttpCompletionOption.ResponseHeadersRead and it will stream as and when as desired.

var postRequest = new HttpRequestMessage(HttpMethod.Post, GetUrl($"/{voice.Id}{(partialClipCallback == null ? string.Empty : "/stream")}", parameters))
{
      Content = payload,
};

var response = await Api.Client.SendAsync(postRequest, partialClipCallback == null ? HttpCompletionOption.ResponseContentRead :  HttpCompletionOption.ResponseHeadersRead, cancellationToken);

https://stackoverflow.com/questions/30475276/why-does-httpclient-postasync-buffer-response

There's the obvious part - if you don't specify HttpCompletionOption.ResponseHeadersRead, the Task will only complete when the whole response is read; you have to store the response data somewhere in the meantime.

Why doesn't PostAsync allow you to specify HttpCompletionOption.ResponseHeadersRead? Probably because it's not really all that useful, most of the time. POST is for posting data, not for retrieving it - that's GET's job. HttpClient was designed around WebAPIs and "REST" services, with proper use of HTTP verbs.

Adapt samples API to allow for filesystem less upload

Feature Request

Is your feature request related to a problem? Please describe.

This is related to the PR and discussion from #25

If I want to add a sample to the voice, I have to write it to the filesystem first (see EditVoiceAsync).
It would be great if we could pass in a ReadOnlyMemory<byte> like we get out the ClipData.

Some preliminary work was already in the above mentioned PR.

Cheers, daniel

Implement an API Proxy

Feature Request

Currently if users want to ship the product in a front end app they risk exposing their apikey when making calls directly to the api.

It should be fairly straight forward to add an API proxy gateway for the client similar to OpenAI-DotNet.

This will give devs the ability to use their own OAuth provider while protecting their API keys.

[Notice] .net 8 upgrade

With .net 6 coming to the EOL this year, the library will be moving to the next .net LTS version 8 in the next major release.

Add Support For Projects

Feature Request

Please add support for the Project API.

Is your feature request related to a problem? Please describe.

Currently, textToSpeech is limited to 5k characters. The only way to support more would be to create a project and pass a file (or URL). This would be very convenient for larger bodies of text.

Describe the solution you'd like

Full support of the Project API. At minimum the ability to add a project and start the conversion would be amazing.

Describe alternatives you've considered

N/A

Additional context

https://elevenlabs.io/docs/api-reference/get-projects

GET Get project by id
POST Add project
DEL Delete project
POST Convert project
GET Get project snapshots
POST Stream project audio
GET Get chapters
GET Get chapter by id
DEL Delete chapter
POST Convert chapter
GET Get chapter snapshots
POST Stream chapter audio
POST Update pronunciation dictionaries

Implement Style Exaggeration and Speaker Boost

The new V2 voices have the option for Style Exaggeration (0.00-1.00), and Speaker Boost (Boolean).

It would be great if those could be implemented into the Voice Settings.

The JSONPropertyNames are:
"style"
"use_speaker_boost"

Loving the library by the way!

(Pull request created. Worked fine when I tried it)
#20

Customize the file name and locations of saved audio clips

If I call TextToSpeechEndpoint() like:
var clipPath = await _elevenlabs_client.TextToSpeechEndpoint.TextToSpeechAsync(text, voice, defaultVoiceSettings, null, @"C:\temp");

The audio file is actually saved in:
C:\temp\ElevenLabs\TextToSpeech\Rachel\x.mp3

Is there a way to specify a save directory and have the api actually save it in that location?

Add Eleven Turbo v2 Model

Feature Request

Suggested Model name, "TurboV2".

public static ElevenLabs.Models.Model TurboV2 { get; } = new ElevenLabs.Models.Model("eleven_turbo_v2");

Net Framework Option

This is already quite great, but I was curious if it was possible to have this be also compiled for Net Framework?

AddVoice Failing

Bug Report

Reported in Discord Post

      There was an error while processing an AddVoice request.
      System.Net.Http.HttpRequestException: Error while copying content to a stream.
       ---> System.IO.IOException: Unable to write data to the transport connection: An existing connection was forcibly closed by the remote host..
       ---> System.Net.Sockets.SocketException (10054): An existing connection was forcibly closed by the remote host.

image

Word Timestamps

A simple question:

Is it possible to obtain start and stop timestamp of every word during transcription? If yes, how?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.