From 7a11a3512f268b39b2ac165163ff7b58cbe1c390 Mon Sep 17 00:00:00 2001 From: Nathan Windisch Date: Tue, 16 Jul 2024 02:28:43 +0100 Subject: [PATCH] Updated the file storage method to use the AI voice name and a hash of the message, to save on compute cycles Signed-off-by: Nathan --- TTSMe/ExtensionMethods.cs | 16 ++++++++++------ TTSMe/TTSClient.cs | 11 ++++------- TTSMe/Voices.cs | 4 ++-- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/TTSMe/ExtensionMethods.cs b/TTSMe/ExtensionMethods.cs index adf2150..124c17b 100644 --- a/TTSMe/ExtensionMethods.cs +++ b/TTSMe/ExtensionMethods.cs @@ -1,16 +1,20 @@ -using EmojiCSharp; +using System.Security.Cryptography; +using System.Text; +using EmojiCSharp; using TwitchLib.Client.Models; namespace TTSMe; public static class ExtensionMethods { + private static byte[] ToBytes(this string str) => Encoding.UTF8.GetBytes(str); + private static string ToHexString(this byte[] bytes) => Convert.ToHexString(bytes); + private static string ToSHA256HashedString(this string str) => SHA256.HashData(str.ToBytes()).ToHexString(); + internal static string? GetStoredVoice(this ChatMessage chatMessage) => Voices.Instance().GetVoice(chatMessage.Username); internal static bool HasStoredVoice(this ChatMessage chatMessage) => Voices.Instance().HasVoice(chatMessage.Username); - // parse out all emojis into their full names - internal static string GetMessageText(this ChatMessage chatMessage) => - EmojiParser.ParseToAliases(chatMessage.Message) - .Replace(":", " colon ") - .Replace("_", " underscore "); + internal static string GetMessageText(this ChatMessage chatMessage) => EmojiParser.ParseToAliases(chatMessage.Message).Replace(":", " colon ").Replace("_", " underscore "); + private static string GetMessageHash(this ChatMessage chatMessage) => chatMessage.GetMessageText().ToSHA256HashedString(); + internal static string GetAudioFilePath(this ChatMessage chatMessage) => Path.Combine(TTSClient.AudioBasePath, $"{chatMessage.GetStoredVoice()!}-{chatMessage.GetMessageHash()}.mp3"); internal static TextToSpeechRequest ToTTSRequest(this ChatMessage chatMessage) => new(chatMessage.GetMessageText(), chatMessage.GetStoredVoice()!); } \ No newline at end of file diff --git a/TTSMe/TTSClient.cs b/TTSMe/TTSClient.cs index e5c6b9c..f2ac9d8 100644 --- a/TTSMe/TTSClient.cs +++ b/TTSMe/TTSClient.cs @@ -1,6 +1,5 @@ using System.Net.Http.Headers; using System.Net.Http.Json; -using System.Security.Cryptography; using System.Text.Json.Serialization; using LibVLCSharp.Shared; using TwitchLib.Client.Models; @@ -14,14 +13,12 @@ public static class TTSClient { }, BaseAddress = new Uri("https://api.openai.com") }; - private const string basePath = "C:/data/twitch/tts"; + public const string AudioBasePath = @"C:\data\twitch\tts"; - public static async Task GenerateSpeech(ChatMessage chatMessage) { + public static async Task GenerateSpeech(ChatMessage chatMessage) { + Console.WriteLine($"Generating speech as {chatMessage.GetAudioFilePath()} for {chatMessage.Username}: {chatMessage.Message}"); HttpResponseMessage response = await httpClient.PostAsJsonAsync("v1/audio/speech", chatMessage.ToTTSRequest()); - byte[] bytes = await response.Content.ReadAsByteArrayAsync(); - string outputPath = Path.Combine(basePath, $"{Guid.NewGuid()}.mp3"); - await File.WriteAllBytesAsync(outputPath, bytes); - return outputPath; + await File.WriteAllBytesAsync(chatMessage.GetAudioFilePath(), await response.Content.ReadAsByteArrayAsync()); } public static async Task PlaySpeech(string path) { diff --git a/TTSMe/Voices.cs b/TTSMe/Voices.cs index 096f6f2..e3f549e 100644 --- a/TTSMe/Voices.cs +++ b/TTSMe/Voices.cs @@ -21,7 +21,7 @@ public class Voices { public static async Task ProcessVoiceMessage(ChatMessage chatMessage) { string? voice = chatMessage.GetStoredVoice(); if (voice is null) return; - string filePath = await TTSClient.GenerateSpeech(chatMessage); - await TTSClient.PlaySpeech(filePath); + if (!File.Exists(chatMessage.GetAudioFilePath())) await TTSClient.GenerateSpeech(chatMessage); + await TTSClient.PlaySpeech(chatMessage.GetAudioFilePath()); } } \ No newline at end of file