Skip to content

Commit

Permalink
ElevenLabs-DotNet 3.4.2 (#78)
Browse files Browse the repository at this point in the history
- Added flash models
- Added stream input support to dubbing endpoint
- Fixed http/https protocol in client settings

---------

Co-authored-by: Austin Hale <32556981+austinbhale@users.noreply.github.com>
  • Loading branch information
StephenHodgson and austinbhale authored Jan 13, 2025
1 parent 9884433 commit b26193a
Show file tree
Hide file tree
Showing 9 changed files with 190 additions and 25 deletions.
64 changes: 57 additions & 7 deletions .github/workflows/Publish-Nuget.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Nuget Publish
name: Build and Publish

on:
push:
Expand All @@ -22,23 +22,36 @@ on:
dotnet-version:
description: ".NET version to use"
required: false
default: "6.0.x"
default: "8.x"

permissions:
contents: read
pages: write
checks: write
id-token: write
pull-requests: write

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false

env:
DOTNET_VERSION: ${{ github.event.inputs.dotnet-version || '6.0.x' }}
PACKAGE_VERSION: ''
DOTNET_VERSION: ${{ github.event.inputs.dotnet-version || '8.x' }}

jobs:
build:
if: ${{ !github.event_name == 'pull_request' || !github.event.pull_request.draft }}
env:
PACKAGE_VERSION: ''
COVERAGE_FILE_PATH: ''
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: actions/setup-dotnet@v3
- uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ env.DOTNET_VERSION }}

Expand All @@ -61,11 +74,18 @@ jobs:
report_individual_runs: true
compare_to_earlier_commit: false

- name: Determine Coverage File Path
if: ${{ github.ref != 'refs/heads/main' && github.event_name != 'push' && always() }}
shell: bash
run: |
COVERAGE_FILE_PATH=$(find ./test-results -name 'coverage.cobertura.xml' | head -n 1)
echo "COVERAGE_FILE_PATH=$COVERAGE_FILE_PATH" >> $GITHUB_ENV
- name: Code Coverage Summary Report
if: ${{ github.ref != 'refs/heads/main' && github.event_name != 'push' && always() }}
uses: irongut/CodeCoverageSummary@v1.3.0
with:
filename: test-results/**/coverage.cobertura.xml
filename: ${{ env.COVERAGE_FILE_PATH }}
badge: true
format: 'markdown'
output: 'both'
Expand Down Expand Up @@ -114,7 +134,7 @@ jobs:
echo "PACKAGE_VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
shell: pwsh

- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
if: always()
with:
name: ElevenLabs-DotNet.${{ env.PACKAGE_VERSION }}
Expand All @@ -124,3 +144,33 @@ jobs:
${{ github.workspace }}/ElevenLabs-DotNet/bin/Release/ElevenLabs-DotNet-Proxy.${{ env.PACKAGE_VERSION }}.nupkg
${{ github.workspace }}/ElevenLabs-DotNet/bin/Release/ElevenLabs-DotNet-Proxy.${{ env.PACKAGE_VERSION }}.symbols.nupkg
if-no-files-found: ignore

docs:
if: ${{ github.ref == 'refs/heads/main' && github.event_name == 'push' }}
needs: build
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ env.DOTNET_VERSION }}

- name: build docfx
run: |
dotnet tool update -g docfx
docfx .docs/docfx.json
- uses: actions/upload-pages-artifact@v3
with:
path: '_site'

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4.0.3
16 changes: 15 additions & 1 deletion ElevenLabs-DotNet/Authentication/ElevenLabsClientSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace ElevenLabs
{
public sealed class ElevenLabsClientSettings
{
internal const string Http = "http://";
internal const string Https = "https://";
internal const string DefaultApiVersion = "v1";
internal const string ElevenLabsDomain = "api.elevenlabs.io";
Expand Down Expand Up @@ -44,7 +45,20 @@ public ElevenLabsClientSettings(string domain, string apiVersion = DefaultApiVer
apiVersion = DefaultApiVersion;
}

Domain = domain.Contains("http") ? domain : $"{Https}{domain}";
var protocol = Https;

if (domain.StartsWith(Http))
{
protocol = Http;
domain = domain.Replace(Http, string.Empty);
}
else if (domain.StartsWith(Https))
{
protocol = Https;
domain = domain.Replace(Https, string.Empty);
}

Domain = $"{protocol}{domain}";
ApiVersion = apiVersion;
BaseRequest = $"/{ApiVersion}/";
BaseRequestUrlFormat = $"{Domain}{BaseRequest}{{0}}";
Expand Down
4 changes: 2 additions & 2 deletions ElevenLabs-DotNet/Dubbing/DubbingEndpoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ public async Task<DubbingProjectMetadata> DubAsync(DubbingRequest request, int?
{
if (request.Files != null)
{
foreach (var (fileName, mediaType, stream) in request.Files)
foreach (var dub in request.Files)
{
await payload.AppendFileToFormAsync("file", stream, fileName, new(mediaType), cancellationToken);
await payload.AppendFileToFormAsync("file", dub.Stream, dub.Name, new(dub.MediaType), cancellationToken);
}
}

Expand Down
33 changes: 25 additions & 8 deletions ElevenLabs-DotNet/Dubbing/DubbingRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public DubbingRequest(
bool? dropBackgroundAudio = null,
bool? useProfanityFilter = null,
string projectName = null)
: this(targetLanguage, null, filePaths, sourceLanguage, numberOfSpeakers, watermark, startTime, endTime, highestResolution, dropBackgroundAudio, useProfanityFilter, projectName)
: this(targetLanguage, null, null, filePaths, sourceLanguage, numberOfSpeakers, watermark, startTime, endTime, highestResolution, dropBackgroundAudio, useProfanityFilter, projectName)
{
}

Expand All @@ -52,13 +52,30 @@ public DubbingRequest(
bool? dropBackgroundAudio = null,
bool? useProfanityFilter = null,
string projectName = null)
: this(targetLanguage, sourceUrl, null, sourceLanguage, numberOfSpeakers, watermark, startTime, endTime, highestResolution, dropBackgroundAudio, useProfanityFilter, projectName)
: this(targetLanguage, sourceUrl, null, null, sourceLanguage, numberOfSpeakers, watermark, startTime, endTime, highestResolution, dropBackgroundAudio, useProfanityFilter, projectName)
{
}

public DubbingRequest(
List<DubbingStream> files,
string targetLanguage,
string sourceLanguage = null,
int? numberOfSpeakers = null,
bool? watermark = null,
int? startTime = null,
int? endTime = null,
bool? highestResolution = null,
bool? dropBackgroundAudio = null,
bool? useProfanityFilter = null,
string projectName = null)
: this(targetLanguage, null, files, null, sourceLanguage, numberOfSpeakers, watermark, startTime, endTime, highestResolution, dropBackgroundAudio, useProfanityFilter, projectName)
{
}

private DubbingRequest(
string targetLanguage,
Uri sourceUrl = null,
List<DubbingStream> files = null,
IEnumerable<string> filePaths = null,
string sourceLanguage = null,
int? numberOfSpeakers = null,
Expand All @@ -78,7 +95,7 @@ private DubbingRequest(
throw new ArgumentException("Either sourceUrl or filePaths must be provided.");
}

var files = new List<(string, string, Stream)>();
files ??= [];

if (filePaths != null)
{
Expand Down Expand Up @@ -113,7 +130,7 @@ private DubbingRequest(
".webm" => "video/webm",
_ => "application/octet-stream"
};
files.Add((fileInfo.Name, mediaType, stream));
files.Add(new(stream, fileInfo.Name, mediaType));
}
}

Expand All @@ -135,7 +152,7 @@ private DubbingRequest(
/// <summary>
/// Files to dub.
/// </summary>
public IReadOnlyList<(string, string, Stream)> Files { get; }
public IReadOnlyList<DubbingStream> Files { get; }

/// <summary>
/// URL of the source video/audio file.
Expand Down Expand Up @@ -204,12 +221,12 @@ private void Dispose(bool disposing)
if (disposing)
{
if (Files == null) { return; }
foreach (var (_, _, stream) in Files)

foreach (var dub in Files)
{
try
{
stream?.Close();
stream?.Dispose();
dub.Dispose();
}
catch (Exception e)
{
Expand Down
64 changes: 64 additions & 0 deletions ElevenLabs-DotNet/Dubbing/DubbingStream.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Licensed under the MIT License. See LICENSE in the project root for license information.

using System;
using System.IO;

namespace ElevenLabs.Dubbing
{
public sealed class DubbingStream : IDisposable
{
public DubbingStream(Stream stream, string name, string mediaType)
{
Stream = stream ?? throw new ArgumentNullException(nameof(stream));

if (Stream.Length == 0)
{
throw new ArgumentException("Stream cannot be empty.");
}

if (!Stream.CanRead)
{
throw new ArgumentException("Stream must be readable.");
}

Name = name ?? throw new ArgumentNullException(nameof(name));

if (string.IsNullOrWhiteSpace(Name))
{
throw new ArgumentException("Name cannot be empty.");
}

MediaType = mediaType ?? throw new ArgumentNullException(nameof(mediaType));

if (string.IsNullOrWhiteSpace(MediaType))
{
throw new ArgumentException("Media type cannot be empty.");
}

if (MediaType.Contains("/"))
{
var parts = MediaType.Split('/');

if (parts.Length != 2 || string.IsNullOrWhiteSpace(parts[0]) || string.IsNullOrWhiteSpace(parts[1]))
{
throw new ArgumentException("Invalid media type.");
}
}
else
{
throw new ArgumentException("Invalid media type.");
}
}

public Stream Stream { get; }

public string Name { get; }

public string MediaType { get; }

public void Dispose()
{
Stream?.Dispose();
}
}
}
6 changes: 5 additions & 1 deletion ElevenLabs-DotNet/ElevenLabs-DotNet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@ All copyrights, trademarks, logos, and assets are the property of their respecti
<SignAssembly>false</SignAssembly>
<IncludeSymbols>true</IncludeSymbols>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Version>3.4.1</Version>
<Version>3.4.2</Version>
<PackageReleaseNotes>
Version 3.4.2
- Added flash models
- Added stream input support to dubbing endpoint
- Fixed http/https protocol in client settings
Version 3.4.1
- Removed text length check in TextToSpeechRequest
Version 3.4.0
Expand Down
12 changes: 12 additions & 0 deletions ElevenLabs-DotNet/Models/Model.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,18 @@ public Model(string id)

#region Predefined Models

/// <summary>
/// Our latest, ultra-low-latency model, generating speech in under 75ms. Best for developer use cases requiring speed and multiple languages.
/// </summary>
[JsonIgnore]
public static Model FlashV2 { get; } = new("eleven_flash_v2");

/// <summary>
/// Our latest, ultra-low-latency English only model, generating speech in under 75ms. Best for developer use cases requiring speed.
/// </summary>
[JsonIgnore]
public static Model FlashV2_5 { get; } = new("eleven_flash_v2_5");

[JsonIgnore]
[Obsolete("Use EnglishV1")]
public static Model MonoLingualV1 => EnglishV1;
Expand Down
6 changes: 3 additions & 3 deletions ElevenLabs-DotNet/TextToSpeech/TextToSpeechRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public TextToSpeechRequest(string text, Model model, VoiceSettings voiceSettings
/// Optional, <see cref="VoiceSettings"/> that will override the default settings in <see cref="Voice.Settings"/>.
/// </param>
/// <param name="model">
/// Optional, <see cref="Model"/> to use. Defaults to <see cref="Model.TurboV2_5"/>.
/// Optional, <see cref="Model"/> to use. Defaults to <see cref="Model.FlashV2"/>.
/// </param>
/// <param name="outputFormat">
/// Output format of the generated audio.<br/>
Expand All @@ -52,7 +52,7 @@ public TextToSpeechRequest(string text, Model model, VoiceSettings voiceSettings
/// <param name="previousRequestIds"></param>
/// <param name="nextRequestIds"></param>
/// <param name="languageCode">
/// Optional, Language code (ISO 639-1) used to enforce a language for the model. Currently only <see cref="Model.TurboV2_5"/> supports language enforcement.
/// Optional, Language code (ISO 639-1) used to enforce a language for the model. Currently only <see cref="Model.TurboV2_5"/> supports language enforcement.
/// For other models, an error will be returned if language code is provided.
/// </param>
/// <param name="withTimestamps"></param>
Expand Down Expand Up @@ -88,7 +88,7 @@ public TextToSpeechRequest(
}

Text = text;
Model = model ?? Models.Model.TurboV2_5;
Model = model ?? Models.Model.FlashV2;
Voice = voice;
VoiceSettings = voiceSettings ?? voice.Settings;
OutputFormat = outputFormat;
Expand Down
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ dotnet add package ElevenLabs-DotNet
---

## Documentation
## [Documentation](https://rageagainstthepixel.github.io/ElevenLabs-DotNet)

> Check out our new api docs!
<https://rageagainstthepixel.github.io/ElevenLabs-DotNet>

### Table of Contents

Expand Down Expand Up @@ -239,7 +243,7 @@ Gets a list of shared voices in the public voice library.

```csharp
var api = new ElevenLabsClient();
var results = await ElevenLabsClient.SharedVoicesEndpoint.GetSharedVoicesAsync();
var results = await api.SharedVoicesEndpoint.GetSharedVoicesAsync();
foreach (var voice in results.Voices)
{
Console.WriteLine($"{voice.OwnerId} | {voice.VoiceId} | {voice.Date} | {voice.Name}");
Expand Down Expand Up @@ -391,7 +395,7 @@ 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 foreach (var chunk in api.DubbingEndpoint.GetDubbedFileAsync(metadata.DubbingId, request.TargetLanguage))
{
await fs.WriteAsync(chunk);
}
Expand Down

0 comments on commit b26193a

Please sign in to comment.