diff --git a/Content.Client/Options/UI/Tabs/AudioTab.xaml.cs b/Content.Client/Options/UI/Tabs/AudioTab.xaml.cs index 0174221e03..ecab7ed010 100644 --- a/Content.Client/Options/UI/Tabs/AudioTab.xaml.cs +++ b/Content.Client/Options/UI/Tabs/AudioTab.xaml.cs @@ -87,6 +87,7 @@ protected override void Dispose(bool disposing) LobbyVolumeSlider, InterfaceVolumeSlider, AnnouncerVolumeSlider, + TtsVolumeSlider, // WD EDIT LobbyMusicCheckBox, RestartSoundsCheckBox, @@ -127,7 +128,7 @@ private void OnApplyButtonPressed(BaseButton.ButtonEventArgs args) _cfg.SetCVar(CCVars.LobbyMusicVolume, LobbyVolumeSlider.Value / 100f * ContentAudioSystem.LobbyMultiplier); _cfg.SetCVar(CCVars.InterfaceVolume, InterfaceVolumeSlider.Value / 100f * ContentAudioSystem.InterfaceMultiplier); _cfg.SetCVar(CCVars.AnnouncerVolume, AnnouncerVolumeSlider.Value / 100f * ContentAudioSystem.AnnouncerMultiplier); - _cfg.SetCVar(WhiteCVars.TtsVolume, TtsVolumeSlider.Value / 100f * ContentAudioSystem.TTSMultiplier); // WD EDIT + _cfg.SetCVar(WhiteCVars.TTSVolume, TtsVolumeSlider.Value / 100f * ContentAudioSystem.TTSMultiplier); // WD EDIT _cfg.SetCVar(CCVars.MaxAmbientSources, (int)AmbienceSoundsSlider.Value); @@ -154,7 +155,7 @@ private void Reset() LobbyVolumeSlider.Value = _cfg.GetCVar(CCVars.LobbyMusicVolume) * 100f / ContentAudioSystem.LobbyMultiplier; InterfaceVolumeSlider.Value = _cfg.GetCVar(CCVars.InterfaceVolume) * 100f / ContentAudioSystem.InterfaceMultiplier; AnnouncerVolumeSlider.Value = _cfg.GetCVar(CCVars.AnnouncerVolume) * 100f / ContentAudioSystem.AnnouncerMultiplier; - TtsVolumeSlider.Value = _cfg.GetCVar(WhiteCVars.TtsVolume) * 100f / ContentAudioSystem.TTSMultiplier; // WD EDIT + TtsVolumeSlider.Value = _cfg.GetCVar(WhiteCVars.TTSVolume) * 100f / ContentAudioSystem.TTSMultiplier; // WD EDIT AmbienceSoundsSlider.Value = _cfg.GetCVar(CCVars.MaxAmbientSources); @@ -183,6 +184,8 @@ private void UpdateChanges() Math.Abs(InterfaceVolumeSlider.Value - _cfg.GetCVar(CCVars.InterfaceVolume) * 100f / ContentAudioSystem.InterfaceMultiplier) < 0.01f; var isAnnouncerVolumeSame = Math.Abs(AnnouncerVolumeSlider.Value - _cfg.GetCVar(CCVars.AnnouncerVolume) * 100f / ContentAudioSystem.AnnouncerMultiplier) < 0.01f; + var isTtsVolumeSame = + Math.Abs(TtsVolumeSlider.Value - _cfg.GetCVar(WhiteCVars.TTSVolume) * 100f / ContentAudioSystem.TTSMultiplier) < 0.01f; // WD EDIT var isAmbientSoundsSame = (int)AmbienceSoundsSlider.Value == _cfg.GetCVar(CCVars.MaxAmbientSources); var isLobbySame = LobbyMusicCheckBox.Pressed == _cfg.GetCVar(CCVars.LobbyMusicEnabled); @@ -193,7 +196,7 @@ private void UpdateChanges() var isEverythingSame = isMasterVolumeSame && isMidiVolumeSame && isAmbientVolumeSame && isAmbientMusicVolumeSame && isAmbientSoundsSame && isLobbySame && isRestartSoundsSame && isEventSame && isAnnouncerDisableMultipleSoundsSame && isAdminSoundsSame && isLobbyVolumeSame - && isInterfaceVolumeSame && isAnnouncerVolumeSame; + && isInterfaceVolumeSame && isAnnouncerVolumeSame && isTtsVolumeSame; // WD EDIT ApplyButton.Disabled = isEverythingSame; ResetButton.Disabled = isEverythingSame; MasterVolumeLabel.Text = @@ -210,6 +213,8 @@ private void UpdateChanges() Loc.GetString("ui-options-volume-percent", ("volume", InterfaceVolumeSlider.Value / 100)); AnnouncerVolumeLabel.Text = Loc.GetString("ui-options-volume-percent", ("volume", AnnouncerVolumeSlider.Value / 100)); + TtsVolumeLabel.Text = + Loc.GetString("ui-options-volume-percent", ("volume", TtsVolumeSlider.Value / 100)); // WD EDIT AmbienceSoundsLabel.Text = ((int)AmbienceSoundsSlider.Value).ToString(); } } diff --git a/Content.Client/_White/TTS/TTSSystem.cs b/Content.Client/_White/TTS/TTSSystem.cs index 64056c2297..d8c9fef280 100644 --- a/Content.Client/_White/TTS/TTSSystem.cs +++ b/Content.Client/_White/TTS/TTSSystem.cs @@ -25,7 +25,7 @@ public sealed class TTSSystem : EntitySystem public override void Initialize() { - _cfg.OnValueChanged(WhiteCVars.TtsVolume, OnTtsVolumeChanged, true); + _cfg.OnValueChanged(WhiteCVars.TTSVolume, OnTtsVolumeChanged, true); SubscribeNetworkEvent(OnPlayTTS); } @@ -33,7 +33,7 @@ public override void Initialize() public override void Shutdown() { base.Shutdown(); - _cfg.UnsubValueChanged(WhiteCVars.TtsVolume, OnTtsVolumeChanged); + _cfg.UnsubValueChanged(WhiteCVars.TTSVolume, OnTtsVolumeChanged); ClearQueues(); } diff --git a/Content.Server/_White/TTS/TTSManager.cs b/Content.Server/_White/TTS/TTSManager.cs index a0a3542fb2..26b558ac05 100644 --- a/Content.Server/_White/TTS/TTSManager.cs +++ b/Content.Server/_White/TTS/TTSManager.cs @@ -1,5 +1,6 @@ using System.Linq; using System.Net.Http; +using System.Net.Http.Json; using System.Text; using System.Text.Json.Serialization; using System.Threading; @@ -51,14 +52,21 @@ public void Initialize() /// OGG audio bytes public async Task ConvertTextToSpeech(string speaker, string text, string pitch, string rate, string? effect = null) { - var url = _cfg.GetCVar(WhiteCVars.TtsApiUrl); + var url = _cfg.GetCVar(WhiteCVars.TTSApiUrl); if (string.IsNullOrWhiteSpace(url)) { _sawmill.Log(LogLevel.Error, nameof(TTSManager), "TTS Api url not specified"); return null; } - var maxCacheSize = _cfg.GetCVar(WhiteCVars.TtsMaxCacheSize); + var token = _cfg.GetCVar(WhiteCVars.TTSApiToken); + if (string.IsNullOrWhiteSpace(token)) + { + _sawmill.Log(LogLevel.Error, nameof(TTSManager), "TTS Api token not specified"); + return null; + } + + var maxCacheSize = _cfg.GetCVar(WhiteCVars.TTSMaxCache); WantedCount.Inc(); var cacheKey = GenerateCacheKey(speaker, text); if (_cache.TryGetValue(cacheKey, out var data)) @@ -70,6 +78,7 @@ public void Initialize() var body = new GenerateVoiceRequest { + ApiToken = token, Text = text, Speaker = speaker, Pitch = pitch, @@ -77,13 +86,11 @@ public void Initialize() Effect = effect }; - var request = CreateRequestLink(url, body); - var reqTime = DateTime.UtcNow; try { var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10)); - var response = await _httpClient.GetAsync(request, cts.Token); + var response = await _httpClient.PostAsJsonAsync(url, body, cts.Token); if (!response.IsSuccessStatusCode) throw new Exception($"TTS request returned bad status code: {response.StatusCode}"); @@ -116,23 +123,6 @@ public void Initialize() } } - private static string CreateRequestLink(string url, GenerateVoiceRequest body) - { - var uriBuilder = new UriBuilder(url); - var query = HttpUtility.ParseQueryString(uriBuilder.Query); - query["speaker"] = body.Speaker; - query["text"] = body.Text; - query["pitch"] = body.Pitch; - query["rate"] = body.Rate; - query["file"] = "1"; - query["ext"] = "ogg"; - if (body.Effect != null) - query["effect"] = body.Effect; - - uriBuilder.Query = query.ToString(); - return uriBuilder.ToString(); - } - public void ResetCache() { _cache.Clear(); @@ -149,6 +139,9 @@ private string GenerateCacheKey(string speaker, string text) private record GenerateVoiceRequest { + [JsonPropertyName("api_token")] + public string ApiToken { get; set; } = ""; + [JsonPropertyName("text")] public string Text { get; set; } = default!; diff --git a/Content.Server/_White/TTS/TTSSystem.cs b/Content.Server/_White/TTS/TTSSystem.cs index 95709de789..611cbd6e74 100644 --- a/Content.Server/_White/TTS/TTSSystem.cs +++ b/Content.Server/_White/TTS/TTSSystem.cs @@ -41,8 +41,8 @@ public sealed partial class TTSSystem : EntitySystem public override void Initialize() { - _cfg.OnValueChanged(WhiteCVars.TtsEnabled, v => _isEnabled = v, true); - _cfg.OnValueChanged(WhiteCVars.TtsApiUrl, url => _apiUrl = url, true); + _cfg.OnValueChanged(WhiteCVars.TTSEnabled, v => _isEnabled = v, true); + _cfg.OnValueChanged(WhiteCVars.TTSApiUrl, url => _apiUrl = url, true); SubscribeLocalEvent(OnEntitySpoke); @@ -171,7 +171,7 @@ private void OnRoundRestartCleanup(RoundRestartCleanupEvent ev) private async void OnRequestTTS(MsgRequestTTS ev) { - var url = _cfg.GetCVar(WhiteCVars.TtsApiUrl); + var url = _cfg.GetCVar(WhiteCVars.TTSApiUrl); if (string.IsNullOrWhiteSpace(url)) return; diff --git a/Content.Shared/_White/CVars.cs b/Content.Shared/_White/CVars.cs index 6730d5a3fb..6d932d3cdf 100644 --- a/Content.Shared/_White/CVars.cs +++ b/Content.Shared/_White/CVars.cs @@ -34,23 +34,41 @@ public static readonly CVarDef /// /// if the TTS system enabled or not. /// - public static readonly CVarDef TtsEnabled = CVarDef.Create("tts.enabled", true, CVar.SERVERONLY); + // ReSharper disable once InconsistentNaming + public static readonly CVarDef TTSEnabled = CVarDef.Create("tts.enabled", true, CVar.SERVERONLY); /// /// URL of the TTS server API. /// - public static readonly CVarDef TtsApiUrl = CVarDef.Create("tts.api_url", "", CVar.SERVERONLY); + // ReSharper disable once InconsistentNaming + public static readonly CVarDef TTSApiUrl = CVarDef.Create("tts.api_url", "", CVar.SERVERONLY); + + /// + /// Auth token of the TTS server API. + /// + // ReSharper disable once InconsistentNaming + public static readonly CVarDef TTSApiToken = + CVarDef.Create("tts.api_token", "", CVar.SERVERONLY | CVar.CONFIDENTIAL); /// /// The volume of TTS playback. /// - public static readonly CVarDef TtsVolume = CVarDef.Create("tts.volume", 0f, CVar.CLIENTONLY | CVar.ARCHIVE); + // ReSharper disable once InconsistentNaming + public static readonly CVarDef TTSVolume = CVarDef.Create("tts.volume", 0f, CVar.CLIENTONLY | CVar.ARCHIVE); /// /// TTS Cache. /// - public static readonly CVarDef TtsMaxCacheSize = + // ReSharper disable once InconsistentNaming + public static readonly CVarDef TTSMaxCache = CVarDef.Create("tts.max_cash_size", 200, CVar.SERVERONLY | CVar.ARCHIVE); + /// + /// Amount of seconds before timeout for API + /// + // ReSharper disable once InconsistentNaming + public static readonly CVarDef TTSApiTimeout = + CVarDef.Create("tts.api_timeout", 5, CVar.SERVERONLY | CVar.ARCHIVE); + #endregion } diff --git a/Resources/Locale/ru-RU/_white/prototypes/voice/tts_voices.ftl b/Resources/Locale/ru-RU/_white/prototypes/voice/tts_voices.ftl index 7c417085ec..38d67d8715 100644 --- a/Resources/Locale/ru-RU/_white/prototypes/voice/tts_voices.ftl +++ b/Resources/Locale/ru-RU/_white/prototypes/voice/tts_voices.ftl @@ -30,7 +30,7 @@ tts-voice-name-asa = Ася tts-voice-name-valentain = Валентин tts-voice-name-chelsea = Челси tts-voice-name-anna = Анна -tts-voice-name-jeanne = Джон +tts-voice-name-jeanne = Жанна tts-voice-name-jasmin = Жасмин tts-voice-name-juelette = Джульета tts-voice-name-arina = Арина