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 namespace LCU.Webapps.Marketing.SPIT.Model
{ {
@@ -8,6 +9,8 @@ namespace LCU.Webapps.Marketing.SPIT.Model
public string SeqApiKey { get; set; } public string SeqApiKey { get; set; }
public string SeqUrl { get; set; } public string SeqUrl { get; set; }
public string SubscriptionKey { get; set; } public string SubscriptionKey { get; set; }
public string SpeechApiKey { get; set; }
public string SpeechEndpoint { get; set; }
public string FetchTokenUri { get; set; } public string FetchTokenUri { get; set; }
public string VoicesUrl { get; set; } public string VoicesUrl { get; set; }
public string OcpApimSubscriptionKey { get; set; } public string OcpApimSubscriptionKey { get; set; }
@@ -17,5 +20,25 @@ namespace LCU.Webapps.Marketing.SPIT.Model
public string SpitRoles { get; set; } public string SpitRoles { get; set; }
public string DefaultLanguageWithCountryCode { get; set; } public string DefaultLanguageWithCountryCode { get; set; }
public List<string> EnabledLanguageOptionCodes { 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; 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) 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/environment-appsettings/appsettings.json", optional: true, reloadOnChange: true);
builder.AddJsonFile("/app/config/workload-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/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-id.json", optional: true, reloadOnChange: true);
builder.AddJsonFile("/vault/secrets/spit-azuread-client-secret.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() public async Task<string> FetchTokenAsync()
{ {
UriBuilder uriBuilder = new($"https://{_spitConfiguration.Region}.{_spitConfiguration.FetchTokenUri}"); var uri = BuildTokenUri();
var uri = uriBuilder.Uri;
var client = _lcuHttpClient.CreateClient(uri); 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(); 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; _spitConfiguration = spitConfiguration;
_fileOperationsApiService = fileOperationsApiService; _fileOperationsApiService = fileOperationsApiService;
_speechConfig = SpeechConfig.FromSubscription(_spitConfiguration.SubscriptionKey, _spitConfiguration.Region); _speechConfig = BuildSpeechConfig();
} }
public async Task<string> SpeechToFile(TextToSpeech textToSpeech) public async Task<string> SpeechToFile(TextToSpeech textToSpeech)
@@ -104,5 +104,17 @@ namespace LCU.Webapps.Marketing.SPIT.Services
return ""; 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 try
{ {
UriBuilder uriBuilder = new UriBuilder($"https://{_spitConfiguration.Region}{_spitConfiguration.VoicesUrl}"); var uri = BuildVoicesUri();
var uri = uriBuilder.Uri;
var token = await _authenticationService.FetchTokenAsync(); var token = await _authenticationService.FetchTokenAsync();
var client = _lcuHttpClient.CreateClient(uri); var client = _lcuHttpClient.CreateClient(uri);
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}"); 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(); var jsonString = await result.Content.ReadAsStringAsync();
voices = JsonConvert.DeserializeObject<List<Voice>>(jsonString); voices = JsonConvert.DeserializeObject<List<Voice>>(jsonString);
} }
@@ -48,5 +47,15 @@ namespace LCU.Webapps.Marketing.SPIT.Services
return voices; 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", "SeqApiKey": "VALUE-IN-KEYVAULT",
"SeqUrl": "https://qa-seq.lcu-internal.com", "SeqUrl": "https://qa-seq.lcu-internal.com",
"SubscriptionKey": "VALUE-IN-KEYVAULT", "SubscriptionKey": "VALUE-IN-KEYVAULT",
"SpeechApiKey": "VALUE-IN-KEYVAULT",
"SpeechEndpoint": "VALUE-IN-KEYVAULT",
"FetchTokenUri": "api.cognitive.microsoft.com/sts/v1.0/issueToken", "FetchTokenUri": "api.cognitive.microsoft.com/sts/v1.0/issueToken",
"VoicesUrl": ".tts.speech.microsoft.com/cognitiveservices/voices/list", "VoicesUrl": ".tts.speech.microsoft.com/cognitiveservices/voices/list",
"OcpApimSubscriptionKey": "Ocp-Apim-Subscription-Key", "OcpApimSubscriptionKey": "Ocp-Apim-Subscription-Key",
@@ -1,12 +1,14 @@
function synthesizeSpeech(subscriptionKey, region, ssml) { function synthesizeSpeech(subscriptionKey, region, endpoint, ssml) {
var SpeechSDK; var SpeechSDK;
if (!!window.SpeechSDK) { if (!!window.SpeechSDK) {
SpeechSDK = 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 audioConfig = SpeechSDK.AudioConfig.fromDefaultSpeakerOutput();
const synthesizer = new SpeechSDK.SpeechSynthesizer(speechConfig, audioConfig); let synthesizer = new SpeechSDK.SpeechSynthesizer(speechConfig, audioConfig);
synthesizer.speakSsmlAsync( synthesizer.speakSsmlAsync(
ssml, ssml,
@@ -21,4 +23,4 @@ function synthesizeSpeech(subscriptionKey, region, ssml) {
synthesizer.close(); synthesizer.close();
synthesizer = undefined; synthesizer = undefined;
}); });
} }
@@ -24,6 +24,22 @@
readOnly: true readOnly: true
subPath: spit-primary-subscription-key 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 - op: add
path: /spec/template/spec/containers/0/volumeMounts/- path: /spec/template/spec/containers/0/volumeMounts/-
value: value:
@@ -38,4 +54,4 @@
name: spit-secrets name: spit-secrets
mountPath: /vault/secrets/spit-azuread-client-secret.json mountPath: /vault/secrets/spit-azuread-client-secret.json
readOnly: true readOnly: true
subPath: spit-azuread-client-secret subPath: spit-azuread-client-secret
@@ -10,6 +10,14 @@
objectName: spit-primary-subscription-key objectName: spit-primary-subscription-key
objectType: secret objectType: secret
objectVersion: "" objectVersion: ""
- |
objectName: speech-api-key
objectType: secret
objectVersion: ""
- |
objectName: speech-endpoint
objectType: secret
objectVersion: ""
- | - |
objectName: spit-azuread-client-id objectName: spit-azuread-client-id
objectType: secret objectType: secret
@@ -18,4 +26,3 @@
objectName: spit-azuread-client-secret objectName: spit-azuread-client-secret
objectType: secret objectType: secret
objectVersion: "" objectVersion: ""