Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using ElevenLabs.History;
using ElevenLabs.Models;
using ElevenLabs.TextToSpeech;
using ElevenLabs.User;
using ElevenLabs.VoiceGeneration;
using ElevenLabs.Voices;
Expand Down Expand Up @@ -1106,7 +1107,7 @@ private async void GenerateSynthesizedText()
Directory.CreateDirectory(downloadDir);
}

voiceClip = await api.TextToSpeechEndpoint.TextToSpeechAsync(new(currentVoiceOption, speechSynthesisTextInput, voiceSettings: currentVoiceSettings, model: currentModelOption));
voiceClip = await api.TextToSpeechEndpoint.TextToSpeechAsync(new TextToSpeechRequest(currentVoiceOption, speechSynthesisTextInput, voiceSettings: currentVoiceSettings, model: currentModelOption));
voiceClip.CopyIntoProject(editorDownloadDirectory);
}
catch (Exception e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,7 @@ public static ElevenLabsSettings Default
public ElevenLabsSettingsInfo Info { get; }

public string BaseRequestUrlFormat => Info.BaseRequestUrlFormat;

public string BaseWebSocketUrlFormat => Info.BaseWebSocketUrlFormat;
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
// Licensed under the MIT License. See LICENSE in the project root for license information.

using System;
using System.Collections.Generic;
using Utilities.WebRequestRest.Interfaces;

namespace ElevenLabs
{
public sealed class ElevenLabsSettingsInfo : ISettingsInfo
{
internal const string WSS = "wss://";
internal const string Http = "http://";
internal const string Https = "https://";
internal const string ElevenLabsDomain = "api.elevenlabs.io";
Expand All @@ -16,8 +18,8 @@ public sealed class ElevenLabsSettingsInfo : ISettingsInfo
/// </summary>
public ElevenLabsSettingsInfo()
{
Domain = ElevenLabsDomain;
BaseRequestUrlFormat = $"{Https}{Domain}/{{0}}/{{1}}";
BaseRequestUrlFormat = $"{Https}{ElevenLabsDomain}/{{0}}/{{1}}";
BaseWebSocketUrlFormat = $"{WSS}{ElevenLabsDomain}/{{0}}/{{1}}";
}

/// <summary>
Expand Down Expand Up @@ -52,10 +54,18 @@ public ElevenLabsSettingsInfo(string domain)

Domain = $"{protocol}{domain}";
BaseRequestUrlFormat = $"{Domain}/{{0}}/{{1}}";
BaseWebSocketUrlFormat = $"{WSS}{ElevenLabsDomain}/{{0}}/{{1}}";
}

public string Domain { get; }

public string BaseRequestUrlFormat { get; }

public string BaseWebSocketUrlFormat { get; }

// ReSharper disable once CollectionNeverUpdated.Local reserved for future use.
private readonly Dictionary<string, string> defaultQueryParameters = new();

internal IReadOnlyDictionary<string, string> DefaultQueryParameters => defaultQueryParameters;
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,36 @@
// Licensed under the MIT License. See LICENSE in the project root for license information.

using System.Collections.Generic;
using System.Linq;
using Utilities.WebRequestRest;

namespace ElevenLabs
{
public abstract class ElevenLabsBaseEndPoint : BaseEndPoint<ElevenLabsClient, ElevenLabsAuthentication, ElevenLabsSettings>
{
protected ElevenLabsBaseEndPoint(ElevenLabsClient client) : base(client) { }
protected override string GetUrl(string endpoint = "", Dictionary<string, string> queryParameters = null)
=> GetEndpoint(client.Settings.BaseRequestUrlFormat, endpoint, queryParameters);

protected string GetWebsocketUri(string endpoint = "", Dictionary<string, string> queryParameters = null)
=> GetEndpoint(client.Settings.BaseWebSocketUrlFormat, endpoint, queryParameters);

private string GetEndpoint(string baseUrlFormat, string endpoint = "", Dictionary<string, string> queryParameters = null)
{
var result = string.Format(baseUrlFormat, ApiVersion, $"{Root}{endpoint}");

foreach (var defaultQueryParameter in client.Settings.Info.DefaultQueryParameters)
{
queryParameters ??= new Dictionary<string, string>();
queryParameters.Add(defaultQueryParameter.Key, defaultQueryParameter.Value);
}

if (queryParameters is { Count: not 0 })
{
result += $"?{string.Join('&', queryParameters.Select(parameter => $"{parameter.Key}={parameter.Value}"))}";
}

return result;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@ internal GeneratedClip(string id, string text, NativeArray<byte> clipData, int s
private string cachedPath;

[Preserve]
public string CachedPath => cachedPath;
public string CachedPath
{
get => cachedPath;
protected set => cachedPath = value;
}

[Preserve]
public NativeArray<byte> ClipData => clipData ??= new NativeArray<byte>(0, Allocator.Persistent);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Licensed under the MIT License. See LICENSE in the project root for license information.

using Newtonsoft.Json;
using System;
using UnityEngine.Scripting;

namespace ElevenLabs
{
[Preserve]
public sealed record PronunciationDictionary
{
[JsonConstructor]
internal PronunciationDictionary(
[JsonProperty("id")] string id,
[JsonProperty("latest_version_id")] string latestVersionId,
[JsonProperty("latest_version_rules_num")] int latestVersionRulesNum,
[JsonProperty("name")] string name,
[JsonProperty("permission_on_resource")] string permissionOnResource,
[JsonProperty("created_by")] string createdBy,
[JsonProperty("creation_time_unix")] long creationTimeUnix,
[JsonProperty("archived_time_unix")] long? archivedTimeUnix,
[JsonProperty("description")] string description)
{
Id = id;
LatestVersionId = latestVersionId;
LatestVersionRulesNum = latestVersionRulesNum;
Name = name;
PermissionOnResource = permissionOnResource;
CreatedBy = createdBy;
CreationTimeUnix = creationTimeUnix;
ArchivedTimeUnix = archivedTimeUnix;
Description = description;
}

[Preserve]
[JsonProperty("id")]
public string Id { get; }

[Preserve]
[JsonProperty("latest_version_id")]
public string LatestVersionId { get; }

[Preserve]
[JsonProperty("latest_version_rules_num")]
public int LatestVersionRulesNum { get; }

[Preserve]
[JsonProperty("name")]
public string Name { get; }

[Preserve]
[JsonProperty("permission_on_resource")]
public string PermissionOnResource { get; }

[Preserve]
[JsonProperty("created_by")]
public string CreatedBy { get; }

[Preserve]
[JsonProperty("creation_time_unix")]
public long CreationTimeUnix { get; }

[Preserve]
[JsonIgnore]
public DateTime CreationTime
=> DateTimeOffset.FromUnixTimeSeconds(CreationTimeUnix).DateTime;

[Preserve]
[JsonProperty("archived_time_unix")]
public long? ArchivedTimeUnix { get; }

[Preserve]
[JsonIgnore]
public DateTime? ArchivedTime
=> ArchivedTimeUnix.HasValue
? DateTimeOffset.FromUnixTimeSeconds(ArchivedTimeUnix.Value).DateTime
: null;

[Preserve]
[JsonProperty("description")]
public string Description { get; }
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Licensed under the MIT License. See LICENSE in the project root for license information.

using Newtonsoft.Json;
using UnityEngine.Scripting;

namespace ElevenLabs
{
[Preserve]
public sealed class PronunciationDictionaryLocator
{
[Preserve]
[JsonConstructor]
public PronunciationDictionaryLocator(
[JsonProperty("pronunciation_dictionary_id")] string id,
[JsonProperty("version_id")] string version)
{
Id = id;
Version = version;
}

[Preserve]
[JsonProperty("pronunciation_dictionary_id")]
public string Id { get; }


[Preserve]
[JsonProperty("version_id")]
public string Version { get; }

[Preserve]
public static implicit operator PronunciationDictionaryLocator(PronunciationDictionary dict)
=> new(dict.Id, dict.LatestVersionId);
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Licensed under the MIT License. See LICENSE in the project root for license information.

using System.Runtime.Serialization;

namespace ElevenLabs
{
public enum TextNormalization
{
[EnumMember(Value = "auto")]
Auto,
[EnumMember(Value = "on")]
On,
[EnumMember(Value = "off")]
Off
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace ElevenLabs
/// Represents timing information for a single character in the transcript
/// </summary>
[Preserve]
public class TimestampedTranscriptCharacter
public sealed class TimestampedTranscriptCharacter
{
[Preserve]
[JsonConstructor]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
// Licensed under the MIT License. See LICENSE in the project root for license information.

using ElevenLabs.Extensions;
using ElevenLabs.Voices;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Unity.Collections;
using UnityEngine;
using UnityEngine.Scripting;
using Utilities.Encoding.OggVorbis;
using Utilities.Encoding.Wav;
using Utilities.WebRequestRest;

namespace ElevenLabs
{
Expand Down Expand Up @@ -34,5 +41,75 @@ internal VoiceClip(string id, string text, Voice voice, NativeArray<byte> clipDa

[Preserve]
public TimestampedTranscriptCharacter[] TimestampedTranscriptCharacters { get; internal set; }

internal async Task SaveAudioToCacheAsync(OutputFormat outputFormat, CacheFormat cacheFormat, CancellationToken cancellationToken)
{
#if PLATFORM_WEBGL
await Task.Yield();
return null;
#else
if (cacheFormat == CacheFormat.None) { return; }

string extension;
AudioType audioType;

if (outputFormat is OutputFormat.MP3_44100_64 or OutputFormat.MP3_44100_96 or OutputFormat.MP3_44100_128 or OutputFormat.MP3_44100_192)
{
extension = "mp3";
audioType = AudioType.MPEG;
}
else
{
switch (cacheFormat)
{
case CacheFormat.Wav:
extension = "wav";
audioType = AudioType.WAV;
break;
case CacheFormat.Ogg:
extension = "ogg";
audioType = AudioType.OGGVORBIS;
break;
default:
throw new ArgumentOutOfRangeException(nameof(cacheFormat), cacheFormat, null);
}
}

await Rest.ValidateCacheDirectoryAsync();

var downloadDirectory = Rest.DownloadCacheDirectory
.CreateNewDirectory(nameof(ElevenLabs))
.CreateNewDirectory(nameof(TextToSpeech))
.CreateNewDirectory(voice.Id);

CachedPath = $"{downloadDirectory}/{Id}.{extension}";

if (!File.Exists(CachedPath))
{
switch (audioType)
{
case AudioType.MPEG:
await File.WriteAllBytesAsync(CachedPath, ClipData.ToArray(), cancellationToken).ConfigureAwait(false);
break;
case AudioType.OGGVORBIS:
var oggBytes = await OggEncoder.ConvertToBytesAsync(
samples: ClipSamples.ToArray(),
sampleRate: outputFormat.GetSampleRate(),
channels: 1,
cancellationToken: cancellationToken).ConfigureAwait(false);
await File.WriteAllBytesAsync(CachedPath, oggBytes, cancellationToken).ConfigureAwait(false);
break;
case AudioType.WAV:
await WavEncoder.WriteToFileAsync(
path: CachedPath,
pcmData: ClipData.ToArray(),
sampleRate: outputFormat.GetSampleRate(),
channels: 1,
cancellationToken: cancellationToken).ConfigureAwait(false);
break;
}
}
#endif // PLATFORM_WEBGL
}
}
}
Loading