This commit is contained in:
Zeeshaun
2026-04-20 15:23:11 +00:00
parent ed133b3470
commit f71bbb7222
10 changed files with 105 additions and 18 deletions
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
namespace LCU.Webapps.Marketing.SPIT.Model
{
@@ -8,6 +9,8 @@ namespace LCU.Webapps.Marketing.SPIT.Model
public string SeqApiKey { get; set; }
public string SeqUrl { get; set; }
public string SubscriptionKey { get; set; }
public string SpeechApiKey { get; set; }
public string SpeechEndpoint { get; set; }
public string FetchTokenUri { get; set; }
public string VoicesUrl { get; set; }
public string OcpApimSubscriptionKey { get; set; }
@@ -17,5 +20,25 @@ namespace LCU.Webapps.Marketing.SPIT.Model
public string SpitRoles { get; set; }
public string DefaultLanguageWithCountryCode { get; set; }
public List<string> EnabledLanguageOptionCodes { get; set; }
public string ResolveSpeechSubscriptionKey()
{
return string.IsNullOrWhiteSpace(SpeechApiKey) ? SubscriptionKey : SpeechApiKey;
}
public bool HasSpeechEndpoint()
{
return !string.IsNullOrWhiteSpace(SpeechEndpoint);
}
public Uri ResolveSpeechEndpointUri()
{
if (!HasSpeechEndpoint())
{
return null;
}
return new Uri(SpeechEndpoint.Trim(), UriKind.Absolute);
}
}
}
@@ -214,7 +214,12 @@
return;
}
await JSRuntime.InvokeVoidAsync("synthesizeSpeech", spitConfiguration.SubscriptionKey, spitConfiguration.Region, _textToSpeech.Ssml);
await JSRuntime.InvokeVoidAsync(
"synthesizeSpeech",
spitConfiguration.ResolveSpeechSubscriptionKey(),
spitConfiguration.Region,
spitConfiguration.SpeechEndpoint,
_textToSpeech.Ssml);
}
public void OpenDirectory(string fileDestination)
@@ -19,8 +19,10 @@ namespace LCU.Webapps.Marketing.SPIT
{
builder.AddJsonFile("/app/config/environment-appsettings/appsettings.json", optional: true, reloadOnChange: true);
builder.AddJsonFile("/app/config/workload-appsettings/appsettings.json", optional: true, reloadOnChange: true);
builder.AddJsonFile("/vault/secrets/lcu-webapps-marketing-spit-seq-api-key.json", optional: true, reloadOnChange: true);
builder.AddJsonFile("/vault/secrets/spit-seq-api-key.json", optional: true, reloadOnChange: true);
builder.AddJsonFile("/vault/secrets/spit-primary-subscription-key.json", optional: true, reloadOnChange: true);
builder.AddJsonFile("/vault/secrets/speech-api-key.json", optional: true, reloadOnChange: true);
builder.AddJsonFile("/vault/secrets/speech-endpoint.json", optional: true, reloadOnChange: true);
builder.AddJsonFile("/vault/secrets/spit-azuread-client-id.json", optional: true, reloadOnChange: true);
builder.AddJsonFile("/vault/secrets/spit-azuread-client-secret.json", optional: true, reloadOnChange: true);
})
@@ -17,13 +17,22 @@ public class AuthenticationService
public async Task<string> FetchTokenAsync()
{
UriBuilder uriBuilder = new($"https://{_spitConfiguration.Region}.{_spitConfiguration.FetchTokenUri}");
var uri = uriBuilder.Uri;
var uri = BuildTokenUri();
var client = _lcuHttpClient.CreateClient(uri);
client.DefaultRequestHeaders.Add(_spitConfiguration.OcpApimSubscriptionKey, _spitConfiguration.SubscriptionKey);
client.DefaultRequestHeaders.Add(_spitConfiguration.OcpApimSubscriptionKey, _spitConfiguration.ResolveSpeechSubscriptionKey());
var result = await client.PostAsync(uriBuilder.Uri.AbsoluteUri, null);
var result = await client.PostAsync(uri.AbsoluteUri, null);
return await result.Content.ReadAsStringAsync();
}
}
private Uri BuildTokenUri()
{
if (_spitConfiguration.HasSpeechEndpoint())
{
return new Uri(_spitConfiguration.ResolveSpeechEndpointUri(), "/sts/v1.0/issueToken");
}
return new Uri($"https://{_spitConfiguration.Region}.{_spitConfiguration.FetchTokenUri}");
}
}
@@ -17,7 +17,7 @@ namespace LCU.Webapps.Marketing.SPIT.Services
{
_spitConfiguration = spitConfiguration;
_fileOperationsApiService = fileOperationsApiService;
_speechConfig = SpeechConfig.FromSubscription(_spitConfiguration.SubscriptionKey, _spitConfiguration.Region);
_speechConfig = BuildSpeechConfig();
}
public async Task<string> SpeechToFile(TextToSpeech textToSpeech)
@@ -104,5 +104,17 @@ namespace LCU.Webapps.Marketing.SPIT.Services
return "";
}
}
private SpeechConfig BuildSpeechConfig()
{
var subscriptionKey = _spitConfiguration.ResolveSpeechSubscriptionKey();
if (_spitConfiguration.HasSpeechEndpoint())
{
return SpeechConfig.FromEndpoint(_spitConfiguration.ResolveSpeechEndpointUri(), subscriptionKey);
}
return SpeechConfig.FromSubscription(subscriptionKey, _spitConfiguration.Region);
}
}
}
@@ -29,15 +29,14 @@ namespace LCU.Webapps.Marketing.SPIT.Services
try
{
UriBuilder uriBuilder = new UriBuilder($"https://{_spitConfiguration.Region}{_spitConfiguration.VoicesUrl}");
var uri = uriBuilder.Uri;
var uri = BuildVoicesUri();
var token = await _authenticationService.FetchTokenAsync();
var client = _lcuHttpClient.CreateClient(uri);
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");
var result = await client.GetAsync(uriBuilder.Uri.AbsoluteUri);
var result = await client.GetAsync(uri.AbsoluteUri);
var jsonString = await result.Content.ReadAsStringAsync();
voices = JsonConvert.DeserializeObject<List<Voice>>(jsonString);
}
@@ -48,5 +47,15 @@ namespace LCU.Webapps.Marketing.SPIT.Services
return voices;
}
private Uri BuildVoicesUri()
{
if (_spitConfiguration.HasSpeechEndpoint())
{
return new Uri(_spitConfiguration.ResolveSpeechEndpointUri(), "/cognitiveservices/voices/list");
}
return new Uri($"https://{_spitConfiguration.Region}{_spitConfiguration.VoicesUrl}");
}
}
}
@@ -5,6 +5,8 @@
"SeqApiKey": "VALUE-IN-KEYVAULT",
"SeqUrl": "https://qa-seq.lcu-internal.com",
"SubscriptionKey": "VALUE-IN-KEYVAULT",
"SpeechApiKey": "VALUE-IN-KEYVAULT",
"SpeechEndpoint": "VALUE-IN-KEYVAULT",
"FetchTokenUri": "api.cognitive.microsoft.com/sts/v1.0/issueToken",
"VoicesUrl": ".tts.speech.microsoft.com/cognitiveservices/voices/list",
"OcpApimSubscriptionKey": "Ocp-Apim-Subscription-Key",
@@ -1,12 +1,14 @@
function synthesizeSpeech(subscriptionKey, region, ssml) {
function synthesizeSpeech(subscriptionKey, region, endpoint, ssml) {
var SpeechSDK;
if (!!window.SpeechSDK) {
SpeechSDK = window.SpeechSDK;
}
const speechConfig = SpeechSDK.SpeechConfig.fromSubscription(subscriptionKey, region);
const speechConfig = endpoint
? SpeechSDK.SpeechConfig.fromEndpoint(new URL(endpoint), subscriptionKey)
: SpeechSDK.SpeechConfig.fromSubscription(subscriptionKey, region);
const audioConfig = SpeechSDK.AudioConfig.fromDefaultSpeakerOutput();
const synthesizer = new SpeechSDK.SpeechSynthesizer(speechConfig, audioConfig);
let synthesizer = new SpeechSDK.SpeechSynthesizer(speechConfig, audioConfig);
synthesizer.speakSsmlAsync(
ssml,
@@ -21,4 +23,4 @@ function synthesizeSpeech(subscriptionKey, region, ssml) {
synthesizer.close();
synthesizer = undefined;
});
}
}
@@ -24,6 +24,22 @@
readOnly: true
subPath: spit-primary-subscription-key
- op: add
path: /spec/template/spec/containers/0/volumeMounts/-
value:
name: spit-secrets
mountPath: /vault/secrets/speech-api-key.json
readOnly: true
subPath: speech-api-key
- op: add
path: /spec/template/spec/containers/0/volumeMounts/-
value:
name: spit-secrets
mountPath: /vault/secrets/speech-endpoint.json
readOnly: true
subPath: speech-endpoint
- op: add
path: /spec/template/spec/containers/0/volumeMounts/-
value:
@@ -38,4 +54,4 @@
name: spit-secrets
mountPath: /vault/secrets/spit-azuread-client-secret.json
readOnly: true
subPath: spit-azuread-client-secret
subPath: spit-azuread-client-secret
@@ -10,6 +10,14 @@
objectName: spit-primary-subscription-key
objectType: secret
objectVersion: ""
- |
objectName: speech-api-key
objectType: secret
objectVersion: ""
- |
objectName: speech-endpoint
objectType: secret
objectVersion: ""
- |
objectName: spit-azuread-client-id
objectType: secret
@@ -18,4 +26,3 @@
objectName: spit-azuread-client-secret
objectType: secret
objectVersion: ""