Untitled

mail@pastecode.io avatar
unknown
csharp
5 months ago
6.3 kB
3
Indexable
using System.Net.WebSockets;
using System.Text.Json;

using Apex.BFF.Application.Common.Interfaces;
using Apex.BFF.Infrastructure.Services.AzureAiTranslation;

using Microsoft.CognitiveServices.Speech;
using Microsoft.CognitiveServices.Speech.Audio;
using Microsoft.CognitiveServices.Speech.Translation;
using Microsoft.Extensions.Options;

namespace Apex.BFF.Infrastructure.Services.AITranslationService
{
    public class TranslationService(IOptions<TranslationServiceSettings> settings) : ITranslationService
    {
        private readonly TranslationServiceSettings _serviceSettings = settings.Value;

        public async Task HandleWebSocketAsync(WebSocket webSocket)
        {
            try
            {
                var v2EndpointInString =
                    $"wss://{_serviceSettings.Region}.stt.speech.microsoft.com/speech/universal/v2";
                var v2EndpointUrl = new Uri(v2EndpointInString);
                var config = SpeechTranslationConfig.FromEndpoint(v2EndpointUrl, _serviceSettings.ApiKey);

                var autoDetectSourceLanguageConfig = AutoDetectSourceLanguageConfig.FromLanguages(["en-US", "es-ES"]);

                config.AddTargetLanguage("es");
                config.AddTargetLanguage("en");

                using var pushStream = AudioInputStream.CreatePushStream();
                using var audioInput = AudioConfig.FromStreamInput(pushStream);
                using var recognizer = new TranslationRecognizer(config, autoDetectSourceLanguageConfig, audioInput);

                recognizer.SessionStarted += (s, e) => Console.WriteLine("Session started");

                recognizer.Recognizing += (s, e) => Console.WriteLine("Recognizing started");

                recognizer.Recognized += async (s, e) =>
                {
                    Console.WriteLine($"Recognized result: Reason={e.Result.Reason}");

                    var lidResult =
                        e.Result.Properties.GetProperty(PropertyId
                            .SpeechServiceConnection_AutoDetectSourceLanguageResult);

                    if (e.Result.Reason == ResultReason.TranslatedSpeech)
                    {
                        await HandleTranslationsAsync(lidResult.Substring(0, 2), e.Result.Translations,
                            e.Result.Text, webSocket);
                    }
                    else
                    {
                        Console.WriteLine("No translation was produced.");
                    }
                };

                recognizer.Canceled += (s, e) =>
                {
                    Console.WriteLine($"Recognition canceled: {e.Reason}");
                    if (e.Reason == CancellationReason.Error)
                    {
                        Console.WriteLine($"Error details: {e.ErrorDetails}");
                    }
                };

                recognizer.SessionStopped += (s, e) => Console.WriteLine("Session stopped");

                await recognizer.StartContinuousRecognitionAsync().ConfigureAwait(false);

                var buffer = new byte[1024 * 4];
                WebSocketReceiveResult result;

                while (webSocket.State == WebSocketState.Open)
                {
                    result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None)
                        .ConfigureAwait(false);

                    if (result.MessageType == WebSocketMessageType.Close)
                    {
                        break;
                    }

                    if (result.Count > 0)
                    {
                        pushStream.Write(buffer, result.Count);
                    }
                }

                // Signal that no more audio will be sent
                pushStream.Close();
                await recognizer.StopContinuousRecognitionAsync().ConfigureAwait(false);

                if (webSocket.State == WebSocketState.Open)
                {
                    await webSocket
                        .CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None)
                        .ConfigureAwait(false);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"WebSocket receive error: {ex.Message}");
                throw;
            }
        }

        private async Task<byte[]> SynthesizeAudioAsync(string text)
        {
            var config = SpeechConfig.FromSubscription(_serviceSettings.ApiKey, _serviceSettings.Region);

            using (var pullAudioStream = new PullAudioOutputStream())
            using (var audioConfig = AudioConfig.FromStreamOutput(pullAudioStream))
            using (var synthesizer = new SpeechSynthesizer(config, audioConfig))
            {
                var result = await synthesizer.SpeakTextAsync(text);

                if (result.Reason == ResultReason.SynthesizingAudioCompleted)
                {
                    return result.AudioData;
                }
                else
                {
                    throw new Exception($"Speech synthesis failed: {result.Reason}");
                }
            }
        }

        private async Task HandleTranslationsAsync(string? sourceLanguage,
            IReadOnlyDictionary<string, string> translations, string originalText, WebSocket webSocket)
        {
            var tasks = translations.Select(async element =>
            {
                if (element.Key != sourceLanguage)
                {
                    var translatedAudio = await SynthesizeAudioAsync(element.Value);
                    var message = new
                    {
                        TranslateLanguage = element.Key,
                        TranslatedText = element.Value,
                        TranslatedAudio = translatedAudio,
                        Originaltext = originalText
                    };

                    var messageBytes = JsonSerializer.SerializeToUtf8Bytes(message);
                    await webSocket.SendAsync(new ArraySegment<byte>(messageBytes), WebSocketMessageType.Text, true,
                        CancellationToken.None);
                }
            });

            await Task.WhenAll(tasks);
        }
    }
}
Leave a Comment