From 5f7f729d89881c69926d93a3f6062f423917c417 Mon Sep 17 00:00:00 2001 From: Stephen Hodgson Date: Mon, 1 May 2023 12:39:56 -0400 Subject: [PATCH] ElevenLabs 1.3.0 (#14) - Added ModelsEndpoint - Updated TextToSpeech.TextToSpeechAsync with optional Model parameter. Defaults to eleven_monolingual_v1 - Added default voices --- .../Test_Fixture_06_Models.cs | 30 +++++++++ ElevenLabs-DotNet/ElevenLabs-DotNet.csproj | 7 ++- ElevenLabs-DotNet/ElevenLabsClient.cs | 4 ++ ElevenLabs-DotNet/Models/Language.cs | 17 ++++++ ElevenLabs-DotNet/Models/Model.cs | 61 +++++++++++++++++++ ElevenLabs-DotNet/Models/ModelsEndpoint.cs | 28 +++++++++ .../TextToSpeech/TextToSpeechEndpoint.cs | 7 ++- .../TextToSpeech/TextToSpeechRequest.cs | 7 ++- ElevenLabs-DotNet/Voices/Voice.cs | 37 ++++++++++- 9 files changed, 190 insertions(+), 8 deletions(-) create mode 100644 ElevenLabs-DotNet-Tests/Test_Fixture_06_Models.cs create mode 100644 ElevenLabs-DotNet/Models/Language.cs create mode 100644 ElevenLabs-DotNet/Models/Model.cs create mode 100644 ElevenLabs-DotNet/Models/ModelsEndpoint.cs diff --git a/ElevenLabs-DotNet-Tests/Test_Fixture_06_Models.cs b/ElevenLabs-DotNet-Tests/Test_Fixture_06_Models.cs new file mode 100644 index 0000000..4114ba3 --- /dev/null +++ b/ElevenLabs-DotNet-Tests/Test_Fixture_06_Models.cs @@ -0,0 +1,30 @@ +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using NUnit.Framework; +using System; +using System.Threading.Tasks; + +namespace ElevenLabs.Tests +{ + internal class Test_Fixture_06_Models : AbstractTestFixture + { + [Test] + public async Task Test_01_GetModels() + { + Assert.NotNull(ElevenLabsClient.ModelsEndpoint); + var models = await ElevenLabsClient.ModelsEndpoint.GetModelsAsync(); + Assert.NotNull(models); + Assert.IsNotEmpty(models); + + foreach (var model in models) + { + Console.WriteLine($"{model.Id} | {model.Name} | {model.Description}"); + + foreach (var language in model.Languages) + { + Console.WriteLine($" {language.Id} | {language.Name}"); + } + } + } + } +} \ No newline at end of file diff --git a/ElevenLabs-DotNet/ElevenLabs-DotNet.csproj b/ElevenLabs-DotNet/ElevenLabs-DotNet.csproj index cebac9a..1f34981 100644 --- a/ElevenLabs-DotNet/ElevenLabs-DotNet.csproj +++ b/ElevenLabs-DotNet/ElevenLabs-DotNet.csproj @@ -14,8 +14,11 @@ RageAgainstThePixel 2023 ElevenLabs, AI, ML, Voice, TTS - 1.2.1 - Version 1.2.1 + 1.3.0 + Version 1.3.0 +- Added ModelsEndpoint +- Updated TextToSpeech.TextToSpeechAsync with optional Model parameter. Defaults to eleven_monolingual_v1 +Version 1.2.1 - Updated docs Version 1.2.0 - Added ability to create voice from Id diff --git a/ElevenLabs-DotNet/ElevenLabsClient.cs b/ElevenLabs-DotNet/ElevenLabsClient.cs index 2b2d2f7..e7d8d7f 100644 --- a/ElevenLabs-DotNet/ElevenLabsClient.cs +++ b/ElevenLabs-DotNet/ElevenLabsClient.cs @@ -1,6 +1,7 @@ // Licensed under the MIT License. See LICENSE in the project root for license information. using ElevenLabs.History; +using ElevenLabs.Models; using ElevenLabs.TextToSpeech; using ElevenLabs.User; using ElevenLabs.VoiceGeneration; @@ -44,6 +45,7 @@ public ElevenLabsClient(ElevenLabsAuthentication elevenLabsAuthentication = null UserEndpoint = new UserEndpoint(this); VoicesEndpoint = new VoicesEndpoint(this); + ModelsEndpoint = new ModelsEndpoint(this); HistoryEndpoint = new HistoryEndpoint(this); TextToSpeechEndpoint = new TextToSpeechEndpoint(this); VoiceGenerationEndpoint = new VoiceGenerationEndpoint(this); @@ -70,6 +72,8 @@ public ElevenLabsClient(ElevenLabsAuthentication elevenLabsAuthentication = null public VoicesEndpoint VoicesEndpoint { get; } + public ModelsEndpoint ModelsEndpoint { get; } + public HistoryEndpoint HistoryEndpoint { get; } public TextToSpeechEndpoint TextToSpeechEndpoint { get; } diff --git a/ElevenLabs-DotNet/Models/Language.cs b/ElevenLabs-DotNet/Models/Language.cs new file mode 100644 index 0000000..442b50d --- /dev/null +++ b/ElevenLabs-DotNet/Models/Language.cs @@ -0,0 +1,17 @@ +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System.Text.Json.Serialization; + +namespace ElevenLabs.Models +{ + public sealed class Language + { + [JsonInclude] + [JsonPropertyName("language_id")] + public string Id { get; private set; } + + [JsonInclude] + [JsonPropertyName("name")] + public string Name { get; private set; } + } +} \ No newline at end of file diff --git a/ElevenLabs-DotNet/Models/Model.cs b/ElevenLabs-DotNet/Models/Model.cs new file mode 100644 index 0000000..a9cb693 --- /dev/null +++ b/ElevenLabs-DotNet/Models/Model.cs @@ -0,0 +1,61 @@ +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace ElevenLabs.Models +{ + public sealed class Model + { + public Model(string id) + { + Id = id; + } + + [JsonInclude] + [JsonPropertyName("model_id")] + public string Id { get; private set; } + + [JsonInclude] + [JsonPropertyName("name")] + public string Name { get; private set; } + + [JsonInclude] + [JsonPropertyName("can_be_finetuned")] + public bool CanBeFineTuned { get; private set; } + + [JsonInclude] + [JsonPropertyName("can_do_text_to_speech")] + public bool CanDoTextToSpeech { get; private set; } + + [JsonInclude] + [JsonPropertyName("can_do_voice_conversion")] + public bool CanDoVoiceConversion { get; private set; } + + [JsonInclude] + [JsonPropertyName("token_cost_factor")] + public double TokenCostFactor { get; private set; } + + [JsonInclude] + [JsonPropertyName("description")] + public string Description { get; private set; } + + [JsonInclude] + [JsonPropertyName("languages")] + public IReadOnlyList Languages { get; private set; } + + public static implicit operator string(Model model) => model.ToString(); + + public override string ToString() => Id; + + #region Predefined Models + + [JsonIgnore] + public static Model MonoLingualV1 { get; } = new Model("eleven_monolingual_v1"); + + [JsonIgnore] + public static Model MultiLingualV1 { get; } = new Model("eleven_multilingual_v1"); + + #endregion Predefined Models + } +} diff --git a/ElevenLabs-DotNet/Models/ModelsEndpoint.cs b/ElevenLabs-DotNet/Models/ModelsEndpoint.cs new file mode 100644 index 0000000..86ef76c --- /dev/null +++ b/ElevenLabs-DotNet/Models/ModelsEndpoint.cs @@ -0,0 +1,28 @@ +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using ElevenLabs.Extensions; +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Threading.Tasks; + +namespace ElevenLabs.Models +{ + public sealed class ModelsEndpoint : BaseEndPoint + { + public ModelsEndpoint(ElevenLabsClient api) : base(api) { } + + protected override string Root => "models"; + + /// + /// Access the different models available to the platform. + /// + /// A list of s you can use. + public async Task> GetModelsAsync() + { + var response = await Api.Client.GetAsync(GetUrl()); + var responseAsString = await response.ReadAsStringAsync(); + return JsonSerializer.Deserialize>(responseAsString, Api.JsonSerializationOptions); + } + } +} diff --git a/ElevenLabs-DotNet/TextToSpeech/TextToSpeechEndpoint.cs b/ElevenLabs-DotNet/TextToSpeech/TextToSpeechEndpoint.cs index 539d341..ca6f1c5 100644 --- a/ElevenLabs-DotNet/TextToSpeech/TextToSpeechEndpoint.cs +++ b/ElevenLabs-DotNet/TextToSpeech/TextToSpeechEndpoint.cs @@ -1,6 +1,7 @@ // Licensed under the MIT License. See LICENSE in the project root for license information. using ElevenLabs.Extensions; +using ElevenLabs.Models; using ElevenLabs.Voices; using System; using System.IO; @@ -25,17 +26,17 @@ public TextToSpeechEndpoint(ElevenLabsClient api) : base(api) { } /// Text input to synthesize speech for. Maximum 5000 characters. /// to use. /// Optional, that will override the default settings in . + /// Optional, to use. Defaults to . /// Optional, The save directory to save the audio clip. /// Optional, deletes the cached file for this text string. Default is false. /// Optional, . /// Downloaded clip path. - public async Task TextToSpeechAsync(string text, Voice voice, VoiceSettings voiceSettings = null, string saveDirectory = null, bool deleteCachedFile = false, CancellationToken cancellationToken = default) + public async Task TextToSpeechAsync(string text, Voice voice, VoiceSettings voiceSettings = null, Model model = null, string saveDirectory = null, bool deleteCachedFile = false, CancellationToken cancellationToken = default) { if (text.Length > 5000) { throw new ArgumentOutOfRangeException(nameof(text), $"{nameof(text)} cannot exceed 5000 characters"); } - var rootDirectory = (saveDirectory ?? Directory.GetCurrentDirectory()).CreateNewDirectory(nameof(ElevenLabs)); var downloadDirectory = rootDirectory.CreateNewDirectory("TextToSpeech"); var fileName = $"{text.GenerateGuid()}.mp3"; @@ -49,7 +50,7 @@ public async Task TextToSpeechAsync(string text, Voice voice, VoiceSetti if (!File.Exists(filePath)) { var defaultVoiceSettings = voiceSettings ?? voice.Settings ?? await Api.VoicesEndpoint.GetDefaultVoiceSettingsAsync(cancellationToken); - var payload = JsonSerializer.Serialize(new TextToSpeechRequest(text, defaultVoiceSettings)).ToJsonStringContent(); + var payload = JsonSerializer.Serialize(new TextToSpeechRequest(text, model ?? Model.MonoLingualV1, defaultVoiceSettings)).ToJsonStringContent(); var response = await Api.Client.PostAsync(GetUrl($"/{voice.Id}"), payload, cancellationToken); await response.CheckResponseAsync(cancellationToken); var responseStream = await response.Content.ReadAsStreamAsync(cancellationToken); diff --git a/ElevenLabs-DotNet/TextToSpeech/TextToSpeechRequest.cs b/ElevenLabs-DotNet/TextToSpeech/TextToSpeechRequest.cs index 249e09c..6ded736 100644 --- a/ElevenLabs-DotNet/TextToSpeech/TextToSpeechRequest.cs +++ b/ElevenLabs-DotNet/TextToSpeech/TextToSpeechRequest.cs @@ -1,5 +1,6 @@ // Licensed under the MIT License. See LICENSE in the project root for license information. +using ElevenLabs.Models; using ElevenLabs.Voices; using System.Text.Json.Serialization; @@ -7,15 +8,19 @@ namespace ElevenLabs.TextToSpeech { public sealed class TextToSpeechRequest { - public TextToSpeechRequest(string text, VoiceSettings voiceSettings) + public TextToSpeechRequest(string text, Model model, VoiceSettings voiceSettings) { Text = text; + Model = model; VoiceSettings = voiceSettings; } [JsonPropertyName("text")] public string Text { get; } + [JsonPropertyName("model_id")] + public string Model { get; } + [JsonPropertyName("voice_settings")] public VoiceSettings VoiceSettings { get; } } diff --git a/ElevenLabs-DotNet/Voices/Voice.cs b/ElevenLabs-DotNet/Voices/Voice.cs index 96ff530..2927628 100644 --- a/ElevenLabs-DotNet/Voices/Voice.cs +++ b/ElevenLabs-DotNet/Voices/Voice.cs @@ -12,8 +12,6 @@ public Voice(string id) Id = id; } - public static implicit operator string(Voice voice) => voice.Id; - [JsonInclude] [JsonPropertyName("voice_id")] public string Id { get; private set; } @@ -45,5 +43,40 @@ public Voice(string id) [JsonInclude] [JsonPropertyName("settings")] public VoiceSettings Settings { get; internal set; } + + public static implicit operator string(Voice voice) => voice.ToString(); + + public override string ToString() => Id; + + #region Premade Voices + + [JsonIgnore] + public static Voice Adam { get; } = new Voice("pNInz6obpgDQGcFmaJgB"); + + [JsonIgnore] + public static Voice Antoni { get; } = new Voice("ErXwobaYiN019PkySvjV"); + + [JsonIgnore] + public static Voice Arnold { get; } = new Voice("VR6AewLTigWG4xSOukaG"); + + [JsonIgnore] + public static Voice Bella { get; } = new Voice("EXAVITQu4vr4xnSDxMaL"); + + [JsonIgnore] + public static Voice Domi { get; } = new Voice("AZnzlk1XvdvUeBnXmlld"); + + [JsonIgnore] + public static Voice Elli { get; } = new Voice("MF3mGyEYCl7XYWbV9V6O"); + + [JsonIgnore] + public static Voice Josh { get; } = new Voice("TxGEqnHWrfWFTfGW9XjX"); + + [JsonIgnore] + public static Voice Rachel { get; } = new Voice("21m00Tcm4TlvDq8ikWAM"); + + [JsonIgnore] + public static Voice Sam { get; } = new Voice("yoZ06aMxZJJ28mfd3POQ"); + + #endregion Premade Voices } }