Skip to content

Commit

Permalink
feat: Add support for Flowery TTS
Browse files Browse the repository at this point in the history
  • Loading branch information
angelobreuer committed Aug 15, 2023
1 parent 17588c3 commit 95fe38e
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Lavalink4NET.Integrations.Lavasrc.TextToSpeech;

public enum TextToSpeechFormat
{
Mp3,
OggOpus,
OggVorbis,
Aac,
Wav,
Flac,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace Lavalink4NET.Integrations.Lavasrc.TextToSpeech;

using Lavalink4NET.Rest.Entities;

public sealed record class TextToSpeechOptions(
string? Voice = null,
float? Speed = null,
bool? Translate = null,
TimeSpan? Silence = null,
TextToSpeechFormat? Format = null,
CacheMode? CacheMode = null)
{
public static TextToSpeechOptions Default { get; } = new();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
namespace Lavalink4NET.Integrations.Lavasrc.TextToSpeech;

using System.Globalization;
using System.Web;
using Lavalink4NET.Rest;
using Lavalink4NET.Rest.Entities;
using Lavalink4NET.Rest.Entities.Tracks;
using Lavalink4NET.Tracks;

public static class TrackManagerExtensions
{
public static async ValueTask<LavalinkTrack> GetTextToSpeechTrackAsync(
this ITrackManager trackManager,
string text,
TextToSpeechOptions? options = null,
LavalinkApiResolutionScope resolutionScope = default,
CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(trackManager);
cancellationToken.ThrowIfCancellationRequested();

options ??= TextToSpeechOptions.Default;

var textToSpeechUri = new Uri($"ftts://{Uri.EscapeDataString(text)}");

// optimize for the most common case where the user wants to use the default options,
// so we don't have to create a new dictionary and copy all the values
if (!ReferenceEquals(TextToSpeechOptions.Default, options))
{
var queryParameters = HttpUtility.ParseQueryString(string.Empty);

if (options.Voice is not null)
{
queryParameters["voice"] = options.Voice;
}

if (options.Speed is not null)
{
queryParameters["speed"] = options.Speed.Value.ToString(CultureInfo.InvariantCulture);
}

if (options.Silence is not null)
{
queryParameters["silence"] = options.Silence.Value.TotalMilliseconds.ToString(CultureInfo.InvariantCulture);
}

if (options.Format is not null)
{
queryParameters["audio_format"] = options.Format.Value switch
{
TextToSpeechFormat.Mp3 => "mp3",
TextToSpeechFormat.OggOpus => "ogg_opus",
TextToSpeechFormat.OggVorbis => "ogg_vorbis",
TextToSpeechFormat.Aac => "aac",
TextToSpeechFormat.Wav => "wac",
TextToSpeechFormat.Flac => "flac",
_ => throw new NotSupportedException(),
};
}

if (options.Translate is not null)
{
queryParameters["translate"] = options.Translate.Value.ToString(CultureInfo.InvariantCulture);
}

textToSpeechUri = new UriBuilder(textToSpeechUri) { Query = queryParameters.ToString(), }.Uri;
}

var loadOptions = new TrackLoadOptions(
SearchMode: TrackSearchMode.None,
StrictSearch: false,
CacheMode: options.CacheMode ?? CacheMode.Dynamic);

var track = await trackManager
.LoadTrackAsync(textToSpeechUri.ToString().TrimEnd('/'), loadOptions, resolutionScope, cancellationToken)
.ConfigureAwait(false);

return track ?? throw new InvalidOperationException("The Flowery TTS track could not be loaded. Ensure Flowery TTS is enabled.");
}
}

0 comments on commit 95fe38e

Please sign in to comment.