https://d226lax1qjow5r.cloudfront.net/blog/blogposts/translate-a-phone-call-with-blazor-signalr-and-azure-dr/Blog_Translate_Phone-Call_1200x600.png

Traduire un appel téléphonique avec Blazor, SignalR et Azure

Publié le November 9, 2020

Temps de lecture : 17 minutes

Les modèles d'apprentissage automatique nous permettent de réaliser toutes sortes de choses intéressantes. Par exemple, la traduction vocale en temps réel. Dans ce tutoriel, nous allons apprendre à traduire un appel reçu sur un numéro Vonage. Nous traduirons ensuite le discours de l'appelant et enverrons tout le texte traduit à notre frontend. L'utilisation d'une application Blazor WebAssembly hébergée dans .NET Core et de SignalR rendra ce processus incroyablement fluide.

Conditions préalables

  • Vous aurez besoin d'une ressource Azure Speech - vous pouvez en créer une en suivant les étapes suivantes ici. Extrayez la région et la valeur de la clé de l'onglet Keys and Endpoint de votre ressource.

  • Le dernier .NET Core SDK installé

  • Visual Studio ou Visual Studio Code. J'utiliserai Visual Studio 2019 pour cette démo.

  • Notre CLI. Si vous ne l'avez pas, vous pouvez l'installer avec npm install @vonage/cli -g

  • ngrok pour les tests. Vous n'avez besoin que de la version gratuite.

Vonage API Account

To complete this tutorial, you will need a Vonage API account. If you don’t have one already, you can sign up today and start building with free credit. Once you have an account, you can find your API Key and API Secret at the top of the Vonage API Dashboard.

Aller directement au code

Si vous disposez déjà de tous les prérequis, vous pouvez sauter ce tutoriel et passer directement au code. L'application est sur GitHub

Spin Up Ngrok

Nous allons utiliser ngrok pour exposer notre application ASP.NET Core exécutée localement à internet. Après avoir installé ngrok, il vous suffira d'exécuter la commande ngrok http 5000 dans votre console. Cela produira quelque chose qui ressemble à ceci :

Example of Ngrok running in the terminalExample of Ngrok running in the terminal

NOTE - ce tutoriel utilise Kestrel pour le débogage local. Si vous souhaitez utiliser IIS Express à la place, veuillez consulter notre explicatif - sur l'utilisation de ngrok avec IIS Express.

La chose essentielle à noter ici est l'URL de transfert - dans mon cas, cette URL est la suivante http://1976e6d913a7.ngrok.io. Lorsque vous recevez un appel sur votre Numbers Vonage, Vonage envoie à votre application ce que l'on appelle un WebHook, qui est simplement une requête HTTP GET, demandant ce que l'on appelle un Nexmo Call Control Object (NCCO). Notre application écoutera sur /webhooks/answer donc l'URL complète dont j'aurai besoin sera http://1976e6d913a7.ngrok.io/webhooks/answer.

Configuration de l'interface de programmation

Si vous n'avez pas encore configuré notre CLI, faites-le en exécutant la commande vonage config:set --apiKey=API_KEY --apiSecret=API_SECRET où la clé et le secret de l'API sont la clé et le secret de l'API qui se trouvent sur la page des paramètres de votre compte Account, sur la page des paramètres de votre compte

Acheter un numéro et créer une application

Maintenant que votre CLI est configuré, nous allons acheter un numéro, créer une Application Vonage et lier le numéro à cette application, ce qui indiquera à Vonage de transférer vers votre application.

Acheter un Numbers

Pour acheter un numéro, utilisez la commande suivante (en remplaçant l'ID de votre pays par US)

vonage numbers:search US vonage numbers:buy [NUMBER] [COUNTRYCODE]

Tapez confirm pour terminer l'opération ; il sortira un numéro que vous avez acheté.

Créer une application

Ensuite, nous allons créer une application. La commande de création d'application prendra deux URL, l'URL de réponse - qui sera le numéro auquel Vonage enverra les appels entrants, et l'URL d'événement, qui sera l'URL à laquelle Vonage enverra les événements qui surviennent à partir de l'un de vos numéros. N'oubliez pas de remplacer 1976e6d913a7 par le hash aléatoire de votre URL ngrok :

vonage apps:create ✔ Application Name … "DTMFInput" ✔ Select App Capabilities › Messages ✔ Create messages webhooks? … yes √ Answer Webhook - URL ... http://1976e6d913a7.ngrok.io/webhooks/answer √ Answer Webhook - Method » GET ✔ Status Webhook - URL … http://1976e6d913a7.ngrok.io/webhooks/events ✔ Status Webhook - Method › POST ✔ Allow use of data for AI training? Read data collection disclosure - https://help.nexmo.com/hc/en-us/articles/4401914566036 … yes

Cette opération répondra par un identifiant d'application et une clé privée. Enregistrez ces deux valeurs. Nous n'utiliserons que l'identifiant de l'application dans ce tutoriel, mais vous utiliserez la clé privée pour autoriser les demandes de votre application.

Lier l'application

Ensuite, nous devons relier le numéro que nous venons d'acheter à notre application. En liant notre numéro, Vonage enverra tous les appels reçus sur ce numéro à l'URL webhook de notre application. Pour ce faire, nous aurons besoin de l'ID de l'application que nous venons de recevoir de la demande de création d'application - qui ressemblera à e7a25242-77a1-42cd-a32e-09febcb375f4et du numéro de téléphone que nous venons d'acheter, et nous lancerons une commande qui ressemblera à ceci :

vonage apps:link --number=VONAGE_NUMBER APP_ID

Construire notre application

Maintenant que nous nous sommes installés et configurés, nous devons construire notre application. Allez dans votre répertoire source typique dans le terminal et exécutez la commande suivante :

dotnet new blazorwasm -ho --no-https -n VonageDotnetTranslator

Cette commande va mettre en place une application Blazor WebAssembly pour vous. Nous n'allons pas configurer SSL, ce qui facilitera le travail avec ngrok.

Il va créer trois fichiers csproj,

  1. VonageDotnetTranslator.Client - c'est ici que le WebAssembly est défini - il sera l'interface de notre application.

  2. VonageDotnetTranslator.Server - Il s'agit du serveur .NET core hébergé pour notre application. C'est dans ce projet que se déroulera l'essentiel de ce que nous devons faire.

  3. VonageDotnetTranslator.Shared - Il s'agit des données partagées entre le client et le serveur.

Ajouter des paquets NuGet

Nous allons utiliser les paquets NuGet suivants pour cet exemple :

  1. Vonage

  2. Microsoft.aspnetcore.signalr.core

  3. Microsoft.CognitiveServices.Speech

  4. Microsoft.aspnetcore.signalr.client

Pour les installer, naviguez d'abord vers VonageDotnetTranslator\Server dans votre terminal et exécutez les commandes suivantes :

dotnet add package Vonage dotnet add package Microsoft.aspnetcore.signalr.core dotnet add package Microsoft.CognitiveServices.Speech

Ensuite, naviguez vers VonageDotnetTranslator\Client dans votre terminal et exécutez :

dotnet add package Microsoft.AspNetcore.SignalR.client

Cette commande installera tous les paquets dont vous aurez besoin. Ouvrez maintenant le fichier VonageDotnetTranslator.sln dans Visual Studio.

Ajouter un modèle

Nous allons créer un modèle de données partagées entre notre client et notre serveur. Pour cela, nous allons utiliser une seule classe, que nous appellerons Translation. Cette classe contiendra un identifiant unique pour l'appel que nous traduisons, le texte d'un événement de traduction donné, la langue parlée et la langue traduite. Créez un fichier Translation.cs dans le projet partagé et ajoutez-y ce qui suit :

public class Translation
 {
     public string UUID { get; set; }
     public string Text { get; set; }
     public string LanguageSpoken { get; set; }
     public string LanguageTranslated { get; set; }
 }

Ajouter un centre de traduction

Nous allons recevoir des événements de traduction dans notre frontend en utilisant une connexion SignalR. Pour communiquer avec notre frontend depuis notre backend, nous allons utiliser une connexion Hub. Pour l'utiliser, nous devons définir un Hub dans notre serveur. Il suffit d'ajouter un dossier Hubs à notre projet de serveur, puis d'ajouter une classe appelée TranslationHub, en faire une classe publique, et la faire hériter de Microsoft.AspNetCore.SignalR.Hubs. Nous n'avons besoin d'aucune autre logique pour cette classe.

Construire notre traducteur

La classe la plus complexe de ce projet sera notre traducteur. Nous l'appellerons le TranslationEngine. Commençons par créer un fichier TranslationEngine.cs dans notre VonageDotnetTranslator.Server projet. Le fichier TranslationEngine va gérer certaines ressources du système sous-jacent. En conséquence, le fichier TranslationEngine implémentera l'interface IDisposable pour nous permettre de nettoyer facilement le projet une fois qu'il est terminé. La définition de la classe devrait ressembler à ceci :

public class TranslationEngine : IDisposable

Définir les constantes

Nous allons ajouter plusieurs constantes à cette classe pour commencer. Ces constantes vont représenter diverses métadonnées sur le flux audio que nous allons gérer. Nous allons ajouter un SAMPLES_PER_SECOND à 16000, un BITS_PER_SAMPLE à 16, a NUMBER_OF_CHANNELS à 1, et a BUFFER_SIZE à 640 (ou 320 * 2).

const int SAMPLES_PER_SECOND = 16000;
const int BITS_PER_SAMPLE = 16;
const int NUMBER_OF_CHANNELS = 1;
const int BUFFER_SIZE = 320 * 2;

Ajouter des champs privés

La classe TranslationEngine comporte un certain nombre de parties mobiles. Nous devrons définir un certain nombre de champs privés. La plupart de ces champs gèrent la configuration du traducteur et du synthétiseur vocal. Quelques champs gèrent les méta-données du moteur de traduction. Nous aurons également une file d'attente concurrente où nous mettrons l'audio en file d'attente pour l'écrire dans notre appel. Quoi qu'il en soit, les champs ressembleront à ceci :

private ConcurrentQueue<byte[]> _audioToWrite = new ConcurrentQueue<byte[]>(); // queue to managed synthesized audio
private readonly IConfiguration _config; //Where Azure Subscription Keys will be stored
private readonly IHubContext<TranslationHub> _hub; // Hub connection we'll use to talk to frontend
private string _uuid; // Unique ID of the call being translated
private string _languageSpoken; // The language being spoken on the call
private string _languageTranslated; // The language being translated to

private SpeechTranslationConfig _translationConfig; // the configuration for the speech translator
private SpeechConfig _speechConfig; // configuration for the speech synthesizer
private PushAudioInputStream _inputStream = AudioInputStream.CreatePushStream(AudioStreamFormat.GetWaveFormatPCM(SAMPLES_PER_SECOND, BITS_PER_SAMPLE, NUMBER_OF_CHANNELS)); //Stream for handling audio input to the translator
private AudioConfig _audioInput; //configuration for the translation audio
private TranslationRecognizer _recognizer; // The translator
private SpeechSynthesizer _synthesizer; // The syntheziser, which will turn translated text into audio
private AudioOutputStream _audioOutputStream; // Output stream from the synthezier
private AudioConfig _outputConfig; // output configuration for the speech syntheizer

Il nécessite un certain nombre d'importations, voici les importations que j'utilise dans cette classe :

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.SignalR;
using Microsoft.CognitiveServices.Speech;
using Microsoft.CognitiveServices.Speech.Audio;
using Microsoft.CognitiveServices.Speech.Translation;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using VonageDotnetTranslator.Server.Hubs;
using VonageDotnetTranslator.Shared;
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;

Ajouter un constructeur

Nous allons avoir un seul constructeur pour cette classe. Il va recevoir deux éléments de type injection de dépendance de la part de l'intergiciel. Un objet IConfiguration objet, où nous stockerons les identifiants Azure de notre ressource Cognitive Services et un objet IHubContext que nous utiliserons pour communiquer avec notre frontend. Nous les assignerons aux champs de classe appropriés, puis nous construirons également quelques configurations et flux pour notre audio.

public TranslationEngine(IConfiguration config, IHubContext<TranslationHub> hub)
{
   _hub = hub;
   _config = config;
   _translationConfig = SpeechTranslationConfig.FromSubscription(
       _config["SUBSCRIPTION_KEY"], _config["REGION"]);
   _speechConfig = SpeechTranslationConfig.FromSubscription(
       _config["SUBSCRIPTION_KEY"], _config["REGION"]);
   _audioInput = AudioConfig.FromStreamInput(_inputStream);
   _audioOutputStream = AudioOutputStream.CreatePullStream();
   _outputConfig = AudioConfig.FromStreamOutput(_audioOutputStream);
}

Traiter la reconnaissance des traductions

Nous devons maintenant ajouter un événement pour gérer les événements de reconnaissance de traduction. Chaque fois que notre traducteur traduira une partie du discours, il déclenchera cet événement. Nous extrairons la traduction de l'événement de reconnaissance. Ensuite, elle est acheminée à travers notre SpeechSynthesizer pour extraire l'audio à lire à l'utilisateur lors de l'appel. Nous construirons ensuite un objet Translation à partir du texte traduit et l'envoyons à tous nos clients qui écoutent le hub. Enfin, nous mettons en file d'attente l'audio synthétisé dans la file d'attente que nous avons créée plus tôt.

private void RecognizerRecognized(object sender, TranslationRecognitionEventArgs e)
{
   var translationLanguage = _languageTranslated.Split("-")[0];
   var translation = e.Result.Translations[translationLanguage].ToString();
   Trace.WriteLine("Recognized: " + translation);
   var ttsAudio = _synthesizer.SpeakTextAsync(translation).Result.AudioData;
   var translationResult = new Translation
   {
       LanguageSpoken = _languageSpoken,
       LanguageTranslated = _languageTranslated,
       Text = translation,
       UUID = _uuid
   };
   _hub.Clients.All.SendAsync("receiveTranslation", translationResult);
   _audioToWrite.Enqueue(ttsAudio);
}

Démarrer le traducteur et le synthétiseur

Lorsque nous recevons un appel, nous allons démarrer notre traducteur et notre synthétiseur. Nous enregistrerons notre événement RecognizerRecognized avec le traducteur et laisser tout démarrer en continu. Puisque nous utilisons un flux d'entrée pour alimenter notre traducteur en audio, celui-ci émettra continuellement des événements de traduction après qu'un certain temps se soit écoulé ou que le traducteur ait détecté une interruption de la parole.

private async Task StartSpeechTranslationEngine(string recognitionLanguage, string targetLanguage)
{
   _translationConfig.SpeechRecognitionLanguage = recognitionLanguage;
   _translationConfig.AddTargetLanguage(targetLanguage);
   _speechConfig.SpeechRecognitionLanguage = targetLanguage;
   _speechConfig.SpeechSynthesisLanguage = targetLanguage;
   _synthesizer = new SpeechSynthesizer(_speechConfig, _outputConfig);
   _recognizer = new TranslationRecognizer(_translationConfig, _audioInput);
   _recognizer.Recognized += RecognizerRecognized;
   await _recognizer.StartContinuousRecognitionAsync();
}

Arrêt de la traduction

Nous aurons besoin d'une méthode pour arrêter le moteur de traduction. Cette méthode désenregistrera notre événement RecognizerRecognized de la base de données _recognizer et appellera la méthode StopContinuousRecognitionAsync sur le moteur de reconnaissance pour le fermer. Cette méthode peut prendre plusieurs secondes pour se fermer, c'est pourquoi nous le faisons de manière asynchrone.

private async Task StopTranscriptionEngine()
{
   if (_recognizer != null)
   {
       _recognizer.Recognized -= RecognizerRecognized;
       await _recognizer.StopContinuousRecognitionAsync();
   }
}

Boucle de traitement principale

Nous recevrons l'audio de nos appels sur une WebSocket, ce qui signifie que nous lirons continuellement l'audio sur la WebSocket. Ensuite, chaque fois que nous obtiendrons des traductions, nous prendrons l'audio synthétisé à partir de nos SpeechSynthesizer et l'écrirons sur la WebSocket pour que l'appelant puisse entendre la traduction. Ce processus se déroulera dans une boucle principale qui continuera à lire les messages sur le WebSocket jusqu'à ce que nous obtenions un statut de fermeture.

Notamment, le premier message que nous recevons de la WebSocket sera un JSON encodé en UTF-8 correspondant à l'élément Headers que nous transmettrons plus tard à l'API Voice de Vonage lorsque nous lui demanderons de créer la WebSocket pour nous. Ce message Headers contiendra un objet Translation que nous avons défini dans notre projet partagé, de sorte que nous désérialiserons le JSON en un objet Translation et utiliser les métadonnées de cet objet pour lancer notre TranslationEngine.

public async Task ReceiveAudioOnWebSocket(HttpContext context, WebSocket webSocket)
{
   var buffer = new byte[BUFFER_SIZE];

   try
   {
       WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
       var config = JsonConvert.DeserializeObject<Translation>(System.Text.Encoding.Default.GetString(buffer));
       _uuid = config.UUID;
       await StartSpeechTranslationEngine(config.LanguageSpoken,
           config.LanguageTranslated);
       _languageSpoken = config.LanguageSpoken;
       _languageTranslated = config.LanguageTranslated;
       while (!result.CloseStatus.HasValue)
       {

           byte[] audio;
           while (_audioToWrite.TryDequeue(out audio))
           {
               const int bufferSize = 640;
               for (var i = 0; i + bufferSize < audio.Length; i += bufferSize)
               {
                   var audioToSend = audio[i..(i + bufferSize)];
                   var endOfMessage = audio.Length > (bufferSize + i);
                   await webSocket.SendAsync(new ArraySegment<byte>(audioToSend, 0, bufferSize), WebSocketMessageType.Binary, endOfMessage, CancellationToken.None);
               }
           }

           result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);

           _inputStream.Write(buffer);
       }
       await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
   }
   catch (Exception e)
   {
       Trace.WriteLine(e.ToString());
   }
   finally
   {
       await StopTranscriptionEngine();
   }
}

Jeter tout ce qui peut l'être

Enfin, nous ferons preuve de civisme en matière de mémoire et nous nous débarrasserons de toutes les ressources non gérées auxquelles nous avons accédé au cours de notre traduction lorsque cet objet sera détruit.

public void Dispose()
{
   _inputStream.Dispose();
   _audioInput.Dispose();
   _recognizer.Dispose();
   _synthesizer.Dispose();
   _audioOutputStream.Dispose();
}

Ajouter un contrôleur Voice

C'est la descente à partir d'ici. Pour l'instant, nous allons ajouter un contrôleur API vide appelé VoiceController à notre dossier Controllers dans notre dossier. Ici, nous allons ajouter une seule route appelée Answer. Le point d'arrivée sera /webhooks/answer. Cette méthode sera une requête GET appelée lorsque votre numéro API Vonage recevra un appel. Elle créera un objet de contrôle d'appel Nexmo (NCCO) indiquant à Vonage de construire une WebSocket vers notre serveur. Comme nous l'avons noté plus tôt, nous passerons un objet Translation dans les en-têtes de cet objet, qui nous indiquera de l'autre côté comment traiter la traduction. Nous prendrons ce NCCO et renverrons son JSON à Vonage pour lui indiquer comment traiter la requête.

[Route("/webhooks/answer")]
[HttpGet]
public ActionResult Answer()
{
   var host = Request.Host.ToString();
   var webSocketAction = new ConnectAction()
   {
       Endpoint = new[]
       {
           new WebsocketEndpoint()
           {
               Uri = $"ws://{host}/ws",
               ContentType="audio/l16;rate=16000",
               Headers = new Translation
               {
                   UUID = Request.Query["uuid"].ToString(),
                   LanguageSpoken = "en-US",
                   LanguageTranslated = "es-MX"
               }
           }
       }
   };
   var ncco = new Ncco(webSocketAction);
   return Ok(ncco.ToString());
}

Configuration de l'intergiciel

Maintenant que nous avons un contrôleur, la dernière chose à faire dans la partie serveur de notre application est de configurer le middleware de l'application. Ouvrir Startup.cs.

ConfigureServices

Dans la méthode ConfigureServices ajouter un appel à l'ajout de SignalR :

services.AddSignalR();

app.UseEndpoints

Ensuite, nous devrons apporter quelques modifications significatives à l'appel de app.UseEndpoints dans la méthode Configure . Tout d'abord, nous allons définir une route vers notre hub à /TranslationHub que nos clients pourront utiliser :

endpoints.MapHub<Hubs.TranslationHub>("/TranslationHub");

Ensuite, nous allons configurer les options WebSocket pour gérer les messages de taille appropriée provenant de Vonage en fonction de l'encodage PCM linéaire de 16khz que nous utilisons :

var webSocketOptions = new WebSocketOptions()
{
  KeepAliveInterval = TimeSpan.FromSeconds(120),
  ReceiveBufferSize = 640
};

app.UseWebSockets(webSocketOptions);

Enfin, nous définirons une route directe vers nos WebSockets dans le délégué app.UseEndpoints délégué. Cette route récupérera le HubContext pour nos WebSockets. TranslationHubmettra à jour le WebSocket et démarrera notre moteur de traduction avec le hub, la configuration, le WebSocket et le httpContext dont il a besoin pour démarrer.

endpoints.Map("/ws", async (context) => {
if (context.WebSockets.IsWebSocketRequest)
{
   var hub = (IHubContext<TranslationHub>)app.ApplicationServices.GetService(typeof(IHubContext<TranslationHub>));
   WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
   using (var engine = new TranslationEngine(Configuration, hub))
   {
       await engine.ReceiveAudioOnWebSocket(context, webSocket);
   }
}
else
{
   context.Response.StatusCode = 400;
}
});

Construire notre Frontend

La dernière chose que nous allons devoir faire est de construire notre frontend. Ironiquement, c'est la partie la plus facile de cet exercice dans le projet VonageDotnetTranslator.Client ajoutez un nouveau composant Razor dans le dossier Pages appelé TranslationComponent.razor. C'est dans ce fichier que nous allons définir notre logique frontale.

Intégrer les dépendances

Nous allons intégrer les dépendances dont nous avons besoin pour travailler avec ce composant de traduction. Ces dépendances incluront le client SignalR, le projet partagé que nous avons utilisé, ainsi que l'injection d'un NavigationManager (pour faciliter le routage), et enfin l'implémentation de IDisposable :

@using Microsoft.AspNetCore.SignalR.Client
@using VonageDotnetTranslator.Shared
@inject NavigationManager NavigationManager
@implements IDisposable

Ajouter du code pour mettre à jour les traductions

Ensuite, dans le bloc @code nous définirons un dictionnaire qui contiendra toutes les traductions que nous obtiendrons de notre serveur, et nous aurons un bloc HubConnection. Dans OnInitializedAsyncnous construirons notre HubConnectionet nous le renverrons vers notre route /TranslationHub définie dans l'intergiciel. Ensuite, chaque fois que l'événement receiveTranslation se déclenche (c'est l'événement que nous envoyons lorsqu'une traduction a lieu), nous mettrons à jour notre dictionnaire de traduction. Si le UUID de l'appel est déjà dans le dictionnaire, nous concaténons le texte de la traduction au texte de la traduction actuelle. Sinon, nous ajouterons un nouvel objet de traduction. Ensuite, nous démarrons la connexion au Hub et ajoutons quelques méthodes supplémentaires pour gérer la connexion et la nettoyer lorsqu'elle est terminée.

@code {
    private Dictionary<string, Translation> _translations = new Dictionary<string, Translation>();
    private HubConnection _hubConnection;
    protected override async Task OnInitializedAsync()
    {
        _hubConnection = new HubConnectionBuilder()
            .WithUrl(NavigationManager.ToAbsoluteUri("/TranslationHub"))
            .Build();
        _hubConnection.On<Translation>("receiveTranslation", (translation) =>
        {
            if (_translations.ContainsKey(translation.UUID))
            {
                _translations[translation.UUID].Text += translation.Text;
            }
            else
            {
                _translations.Add(translation.UUID, translation);
            }
            StateHasChanged();
        });
        await _hubConnection.StartAsync();
    }
    public bool IsConnected => _hubConnection.State == HubConnectionState.Connected;

    public void Dispose()
    {
        _ = _hubConnection.DisposeAsync();
    }
}

Ajouter notre point de vue

Ensuite, nous ajouterons un tableau qui contiendra toutes nos traductions. Ce tableau aura des en-têtes correspondant aux propriétés de l'objet Translation et nous l'alimenterons directement à partir de notre collection _translations collection.

<h3>Translation</h3>
<table class="table">
    <thead>
        <tr>
            <th>Uuid</th>
            <th>Language Spoken</th>
            <th>Language Translated To</th>
            <th>Text</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var translation in _translations.Values)
        {
            <tr>
                <td>@translation.UUID</td>
                <td>@translation.LanguageSpoken</td>
                <td>@translation.LanguageTranslated</td>
                <td>@translation.Text</td>
            </tr>
        }
    </tbody>
</table>

Ajouter à l'index

La dernière chose à faire est d'ajouter le TranslationComponent au fichier index.razor au fichier Pour ce faire, ouvrez Index.razoret supprimez son contenu, à l'exception de la directive @page et ajoutez-la :

Configurer l'application

La dernière chose à faire est d'ajouter les deux éléments de configuration Azure au fichier VonageDotnetTranslation.Server/appsettings.json au fichier Ajoutez deux champs à l'objet de base, SUBSCRIPTION_KEY et REGIONet définissez-les en fonction de votre clé d'abonnement et de votre région.

Test

C'est tout ce que vous avez à faire pour construire votre traducteur vocal ! Il ne reste plus qu'à le tester ou à lancer l'application depuis le répertoire VonageDotnetTranslation/Server avec dotnet run ou utilisez f5 ou le bouton play.

Note - Si vous utilisez IIS Express, vous devrez consulter notre guide d'utilisation de ngrok avec IIS Express

Dans notre VoiceController nous avons fixé la langue de traduction à l'espagnol et la langue parlée à l'anglais américain - vous pouvez changer cela facilement - voir la section langues prises en charge pour connaître les langues prises en charge par Azure.

Pousser plus loin

Les WebSockets permettent toutes sortes de cas d'utilisation puissants lorsqu'ils sont combinés avec les Azure Cognitive Services. En plus des traductions, vous pouvez également faire de la transcription régulière ou même de l'analyse de sentiments ! Les API de Vonage permettent toutes sortes d'intégrations très flexibles et relativement faciles à construire avec le RTC et la VoIP.

Ressources

  • La source de cette démo se trouve sur GitHub

Partager:

https://a.storyblok.com/f/270183/384x384/73d57fd8eb/stevelorello.png
Steve LorelloAnciens de Vonage

Ancien développeur .NET Advocate @Vonage, ingénieur logiciel polyglotte full-stack, AI/ML