
Teilen Sie:
Ehemaliger .NET Developer Advocate @Vonage, polyglotter Software-Ingenieur, AI/ML
Übersetzen Sie einen Telefonanruf mit Blazor, SignalR und Azure
Mit Modellen des maschinellen Lernens können wir alle möglichen tollen Dinge tun. Zum Beispiel die Sprachübersetzung in Echtzeit. In diesem Tutorial lernen wir, wie man einen Anruf, der über eine Vonage-Nummer eingeht, übersetzt. Wir werden dann die Sprache des Anrufers übersetzen und den gesamten übersetzten Text an unser Frontend senden. Die Verwendung einer mit .NET Core gehosteten Blazor WebAssembly App und SignalR macht diesen Prozess unglaublich nahtlos.
Voraussetzungen
Sie benötigen eine Azure Speech Resource - Sie können eine erstellen, indem Sie die Schritte hier. Ziehen Sie die Region und den Schlüsselwert aus dem
Keys and EndpointRegisterkarte Ihrer Ressource.Das neueste .NET Core SDK installiert
Visual Studio oder Visual Studio Code. Ich werde Visual Studio 2019 für diese Demo verwenden
Unser CLI. Wenn Sie es nicht haben, können Sie es installieren mit
npm install @vonage/cli -gngrok zum Testen. Sie benötigen nur die kostenlose Version.
Vonage API-Konto
Um dieses Tutorial durchzuführen, benötigen Sie ein Vonage API-Konto. Wenn Sie noch keines haben, können Sie sich noch heute anmelden und mit einem kostenlosen Guthaben beginnen. Sobald Sie ein Konto haben, finden Sie Ihren API-Schlüssel und Ihr API-Geheimnis oben auf dem Vonage-API-Dashboard.
Direkt zum Code springen
Wenn Sie bereits alle Voraussetzungen erfüllt haben, können Sie dieses Tutorial überspringen und direkt mit dem Code beginnen. Die Anwendung ist auf GitHub
Spin Up Ngrok
Wir werden ngrok verwenden, um unsere lokal ausgeführte ASP.NET Core-Anwendung für das Internet freizugeben. Nachdem Sie ngrok installiert haben, ist es so einfach wie das Ausführen des Befehls ngrok http 5000 in Ihrer Konsole auszuführen. Das Ergebnis sieht dann etwa so aus:
Example of Ngrok running in the terminal
HINWEIS - dieses Tutorial verwendet Kestrel für das lokale Debugging. Wenn Sie stattdessen IIS Express verwenden möchten, lesen Sie bitte unseren Erläuterung - über die Verwendung von ngrok mit IIS Express.
Entscheidend ist hier die Weiterleitungs-URL - in meinem Fall lautet diese URL http://1976e6d913a7.ngrok.io. Wenn Sie einen Anruf auf Ihrer Vonage-Nummer erhalten, sendet Vonage Ihrer Anwendung einen so genannten WebHook, d. h. eine HTTP-GET-Anfrage, die nach einem so genannten Nexmo Call Control Object (NCCO) fragt. Unsere Anwendung hört auf /webhooks/answer also wird die gesamte URL, die ich benötige, sein http://1976e6d913a7.ngrok.io/webhooks/answer.
CLI einrichten
Wenn Sie unsere CLI noch nicht eingerichtet haben, führen Sie dazu den Befehl vonage config:set --apiKey=API_KEY --apiSecret=API_SECRET aus, wobei der API-Schlüssel und das Geheimnis der API-Schlüssel und das Geheimnis sind, die Sie auf Ihrer Einstellungen Ihres Accounts
Nummer kaufen und Antrag erstellen
Nun, da Ihre CLI eingerichtet ist, werden wir eine Nummer erwerben, eine Vonage-Anwendung erstellen und die Nummer mit dieser Anwendung verknüpfen, wodurch Vonage angewiesen wird, an Ihre Anwendung weiterzuleiten.
Kaufen Sie eine Nummer
Um eine Nummer zu kaufen, verwenden Sie den folgenden Befehl (ersetzen Sie Ihre Länder-ID durch US)
Geben Sie confirm um den Vorgang abzuschließen; es wird eine Nummer ausgegeben, die Sie gekauft haben.
Eine Anwendung erstellen
Als nächstes werden wir eine Anwendung erstellen. Der Befehl "Anwendung erstellen" benötigt zwei URLs: die Antwort-URL, an die Vonage eingehende Anrufe sendet, und die Ereignis-URL, an die Vonage Ereignisse sendet, die von einer Ihrer Nummern ausgehen. Denken Sie daran, die URL 1976e6d913a7 durch den zufälligen Hashwert für Ihre ngrok-URL zu ersetzen:
Dieser Vorgang wird mit einer Anwendungs-ID und einem privaten Schlüssel beantwortet. Speichern Sie diese beiden Werte. Wir werden in diesem Tutorial nur die Anwendungs-ID verwenden, aber Sie verwenden den privaten Schlüssel, um Ihre Anwendungsanfragen zu autorisieren.
Verknüpfen Sie die Anwendung
Als nächstes müssen wir unsere neu erworbene Nummer mit unserer Anwendung verknüpfen. Durch die Verknüpfung unserer Nummer wird Vonage angewiesen, alle auf dieser Nummer eingehenden Anrufe an die Webhook-URL unserer Anwendung zu senden. Dazu benötigen wir die Anwendungs-ID, die wir gerade von der Anfrage "create app" erhalten haben - sie sieht aus wie e7a25242-77a1-42cd-a32e-09febcb375f4und die Telefonnummer, die wir gerade gekauft haben, und wir führen einen Befehl aus, der wie folgt aussieht:
Unsere App erstellen
Nachdem wir uns nun eingerichtet und konfiguriert haben, müssen wir nun unsere Anwendung erstellen. Gehen Sie im Terminal in Ihr typisches Quellverzeichnis und führen Sie den folgenden Befehl aus:
Mit diesem Befehl wird eine Blazor WebAssembly-Anwendung für Sie erstellt. Wir werden SSL nicht konfigurieren, was die Arbeit mit ngrok erleichtert.
Es werden drei csproj-Dateien erstellt,
VonageDotnetTranslator.Client - hier wird die WebAssembly definiert - sie wird das Frontend für unsere Anwendung sein.
VonageDotnetTranslator.Server - Dies wird der .NET Core gehostete Server für unsere Anwendung sein. Dieses Projekt ist, wo der Großteil von dem, was wir tun müssen, passieren wird.
VonageDotnetTranslator.Shared - Dies sind die gemeinsamen Daten zwischen dem Client und dem Server.
NuGet-Pakete hinzufügen
Für dieses Beispiel werden wir die folgenden NuGet-Pakete verwenden:
Vonage
Microsoft.aspnetcore.signalr.core
Microsoft.CognitiveServices.Speech
Microsoft.aspnetcore.signalr.client
Um diese zu installieren, navigieren Sie zunächst zu VonageDotnetTranslator\Server in Ihrem Terminal und führen Sie die folgenden Befehle aus:
Navigieren Sie dann zu VonageDotnetTranslator\Client in Ihrem Terminal und führen Sie es aus:
Dieser Befehl installiert alle Pakete, die Sie benötigen werden. Öffnen Sie nun die Datei VonageDotnetTranslator.sln in Visual Studio.
Ein Modell hinzufügen
Wir werden ein Modell der Daten erstellen, die von unserem Client und Server gemeinsam genutzt werden. Dazu verwenden wir nur eine einzige Klasse, die wir Translation. Diese Klasse enthält eine eindeutige Kennung für den Anruf, den wir übersetzen, den Text eines bestimmten Übersetzungsereignisses, die gesprochene Sprache und die übersetzte Sprache. Erstellen Sie eine Datei Translation.cs in dem gemeinsamen Projekt und fügen Sie Folgendes hinzu:
public class Translation
{
public string UUID { get; set; }
public string Text { get; set; }
public string LanguageSpoken { get; set; }
public string LanguageTranslated { get; set; }
} Hinzufügen eines Übersetzungszentrums
Wir werden die Übersetzungsereignisse in unserem Frontend über eine SignalR-Verbindung empfangen. Um von unserem Backend zu unserem Frontend zu kommunizieren, werden wir eine Hub-Verbindung verwenden. Um diese zu verwenden, müssen wir einen Hub in unserem Server definieren. Fügen Sie einfach einen Hubs-Ordner zu unserem Server-Projekt hinzu, fügen Sie dann eine Klasse namens TranslationHubhinzu, machen Sie sie zu einer öffentlichen Klasse und lassen Sie sie erben von Microsoft.AspNetCore.SignalR.Hubs. Wir brauchen keine weitere Logik für diese Klasse.
Bauen Sie unseren Übersetzer
Die komplexeste Klasse in diesem Projekt wird unser Übersetzer sein. Diesen werden wir als TranslationEngine. Beginnen wir mit der Erstellung einer Datei TranslationEngine.cs in unserem VonageDotnetTranslator.Server Projekt. Die TranslationEngine wird einige zugrunde liegende Systemressourcen verwalten. Folgerichtig wird die TranslationEngine die Schnittstelle IDisposable Schnittstelle implementieren, damit wir sie nach ihrer Beendigung einfach aufräumen können. Die Klassendefinition sollte wie folgt aussehen:
public class TranslationEngine : IDisposable Konstanten definieren
Wir werden dieser Klasse mehrere Konstanten hinzufügen, um den Einstieg zu erleichtern. Bei diesen Konstanten handelt es sich um verschiedene Metadaten über den Audiostrom, den wir verarbeiten werden. Wir fügen eine SAMPLES_PER_SECOND bei 16000, eine BITS_PER_SAMPLE bei 16, a NUMBER_OF_CHANNELS bei 1 und a BUFFER_SIZE bei 640 (oder 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; Private Felder hinzufügen
Die Klasse TranslationEngine hat eine ganze Reihe von beweglichen Teilen. Wir müssen eine Reihe von privaten Feldern definieren. Die meisten dieser Felder behandeln die Konfiguration des Übersetzers und des Sprachsynthesizers. Wir haben einige Felder, die die Metadaten für die Übersetzungsmaschine verwalten. Wir werden auch eine gleichzeitige Warteschlange haben, in der wir Audio in eine Warteschlange stellen, um es in unseren Aufruf zurückzuschreiben. Unabhängig davon werden die Felder wie folgt aussehen:
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
Es erfordert eine Reihe von Importen, hier sind die Importe, die ich in dieser Klasse verwende:
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; Konstrukteur hinzufügen
Wir werden einen einzigen Konstruktor für diese Klasse haben. Er wird zwei Elemente vom Typ Dependency Injection von der Middleware erhalten. Ein IConfiguration Objekt, in dem wir die Azure Credentials von unserer Cognitive Services-Ressource speichern werden, und ein IHubContext Objekt, das wir für die Kommunikation mit unserem Frontend verwenden werden. Wir werden diese den entsprechenden Klassenfeldern zuweisen und dann werden wir auch einige Konfigurationen und Streams für unser Audio konstruieren.
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);
}
Handle Translation Recognition
Wir müssen nun ein Ereignis hinzufügen, um die Erkennungsereignisse der Übersetzung zu behandeln. Immer wenn unser Übersetzer einen Teil der Sprache übersetzt, wird er dieses Ereignis auslösen. Wir werden die Übersetzung aus dem Erkennungsereignis herausziehen. Dann wird sie durch unser SpeechSynthesizer um das Audio für die Wiedergabe an den Benutzer während des Anrufs herauszuziehen. Wir erstellen dann ein Translation Objekt aus dem übersetzten Text und senden es an alle unsere Clients, die den Hub abhören. Zum Schluss wird das synthetisierte Audio in die Warteschlange eingeordnet, die wir zuvor erstellt haben.
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);
} Starten Sie den Übersetzer und Synthesizer
Wenn wir einen Anruf erhalten, werden wir unseren Übersetzer und Synthesizer starten. Wir registrieren unser RecognizerRecognized Ereignis beim Übersetzer und lassen alles kontinuierlich anlaufen. Da wir einen Eingabestrom verwenden, um unseren Übersetzer mit Audio zu versorgen, werden kontinuierlich Übersetzungsereignisse ausgegeben, nachdem eine bestimmte Zeit verstrichen ist oder der Übersetzer eine Sprachunterbrechung erkennt.
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();
} Übersetzung stoppen
Wir brauchen eine Methode, um die Übersetzungsmaschine zu stoppen. Diese Methode deregistriert unser RecognizerRecognized Ereignis aus dem _recognizer und ruft die Methode StopContinuousRecognitionAsync beim Erkenner auf, um ihn zu beenden. Das Beenden dieser Methode kann mehrere Sekunden dauern, weshalb wir es asynchron durchführen.
private async Task StopTranscriptionEngine()
{
if (_recognizer != null)
{
_recognizer.Recognized -= RecognizerRecognized;
await _recognizer.StopContinuousRecognitionAsync();
}
} Hauptverarbeitungsschleife
Wir werden Audio von unseren Anrufen über einen WebSocket empfangen, was bedeutet, dass wir kontinuierlich Audio aus dem WebSocket lesen werden. Wenn wir dann Übersetzungen erhalten, nehmen wir das synthetisierte Audio von unserem SpeechSynthesizer und schreiben es über den WebSocket zurück, so dass der Anrufer die Übersetzung hören kann. Dieser Prozess wird in einer Hauptschleife ablaufen, die so lange Nachrichten aus dem WebSocket liest, bis der Status "close" erreicht ist.
Die erste Nachricht, die wir vom WebSocket erhalten, ist ein UTF-8 kodiertes JSON, das der Datei Headers die wir später an die Vonage Voice API zurückgeben werden, wenn wir sie bitten, den WebSocket für uns zu erstellen. Diese Headers enthält ein Translation Objekt, das wir in unserem gemeinsamen Projekt definiert haben, also deserialisieren wir das JSON in ein Translation Objekt deserialisieren und die Metadaten daraus verwenden, um unsere TranslationEngine zu starten.
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();
}
}
Entsorgen Sie alles
Schließlich werden wir uns wie gute Speicherbewohner verhalten und alle nicht verwalteten Ressourcen, auf die wir während unserer Übersetzung zugegriffen haben, entsorgen, wenn dieses Objekt zerstört wird.
public void Dispose()
{
_inputStream.Dispose();
_audioInput.Dispose();
_recognizer.Dispose();
_synthesizer.Dispose();
_audioOutputStream.Dispose();
} Einen Voice Controller hinzufügen
Von hier an geht es nur noch bergab. Für den Moment fügen wir einen leeren API-Controller namens VoiceController zu unserem Controllers Ordner. Hier fügen wir eine einzelne Route namens Answer. Der Endpunkt wird sein /webhooks/answer. Diese Methode wird eine GET-Anfrage sein, die aufgerufen wird, wenn Ihre Vonage-API-Nummer einen Anruf erhält. Es wird ein Nexmo Call Control Object (NCCO) erstellt, das Vonage anweist, einen WebSocket zu unserem Server aufzubauen. Wie wir bereits erwähnt haben, werden wir ein Translation Objekt durch die Header dieses Objekts, das uns auf der anderen Seite sagt, wie die Übersetzung zu behandeln ist. Wir nehmen dieses NCCO und geben es als JSON an Vonage zurück, um ihm mitzuteilen, wie die Anfrage zu behandeln ist.
[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());
} Middleware konfigurieren
Da wir nun einen Controller haben, müssen wir als letztes im Server-Teil unserer Anwendung die Middleware der Anwendung konfigurieren. Öffnen Sie Startup.cs.
ConfigureServices
Innerhalb der ConfigureServices Methode fügen Sie einen Aufruf zum Hinzufügen von SignalR:
services.AddSignalR(); app.UseEndpoints
Als Nächstes müssen wir einige wesentliche Änderungen an dem app.UseEndpoints Aufruf in der Configure Methode vornehmen. Zunächst werden wir eine Route zu unserem Hub unter /TranslationHub die unsere Clients verwenden können:
endpoints.MapHub<Hubs.TranslationHub>("/TranslationHub");
Als Nächstes richten wir die WebSocket-Optionen ein, um die Nachrichten von Vonage in der richtigen Größe zu verarbeiten, basierend auf der von uns verwendeten linearen 16khz-PCM-Kodierung:
var webSocketOptions = new WebSocketOptions()
{
KeepAliveInterval = TimeSpan.FromSeconds(120),
ReceiveBufferSize = 640
};
app.UseWebSockets(webSocketOptions);Schließlich werden wir eine direkte Route zu unseren WebSockets im app.UseEndpoints Delegaten. Diese Route wird den HubContext für unseren TranslationHubbeziehen, den WebSocket aktualisieren und unsere Übersetzungsmaschine mit dem Hub, der Konfiguration, dem WebSocket und dem httpContext starten, die sie benötigt, um loszulegen.
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;
}
});
Bauen Sie unser Frontend
Das letzte, was wir tun müssen, ist, unser Frontend zu erstellen. Ironischerweise ist dies der einfachste Teil dieser Übung im VonageDotnetTranslator.Client Projekt eine neue Razor-Komponente in den Pages Ordner mit dem Namen TranslationComponent.razor. In dieser Datei werden wir unsere Frontend-Logik definieren.
Abhängigkeiten einbeziehen
Wir werden die Abhängigkeiten, die wir für die Arbeit mit dieser Übersetzungskomponente benötigen, einbinden. Zu diesen Abhängigkeiten gehören der SignalR Client, das Shared Project, das wir verwendet haben, sowie das Einfügen eines NavigationManager (um beim Routing zu helfen) und schließlich die Implementierung von IDisposable:
@using Microsoft.AspNetCore.SignalR.Client
@using VonageDotnetTranslator.Shared
@inject NavigationManager NavigationManager
@implements IDisposable Code zum Aktualisieren von Übersetzungen hinzufügen
Als nächstes wird im @code Block werden wir ein Wörterbuch definieren, in dem alle Übersetzungen, die wir von unserem Server erhalten, gespeichert werden, und wir werden ein HubConnection. In OnInitializedAsyncerstellen wir unser HubConnectionund verweisen damit auf unsere /TranslationHub Route, die in der Middleware definiert ist. Wenn dann das receiveTranslation Ereignis ausgelöst wird (dies ist das Ereignis, das wir senden, wenn eine Übersetzung stattfindet), aktualisieren wir unser Übersetzungswörterbuch. Wenn die UUID für den Aufruf bereits im Wörterbuch enthalten ist, wird der Übersetzungstext an den Text der aktuellen Übersetzung angehängt. Andernfalls fügen wir ein neues Übersetzungsobjekt hinzu. Dann starten wir die Hub-Verbindung und fügen ein paar zusätzliche Methoden hinzu, um die Verbindung zu verwalten und nach Beendigung aufzuräumen.
@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();
}
}
Unsere Ansicht hinzufügen
Als Nächstes fügen wir eine Tabelle hinzu, die alle unsere Übersetzungen enthalten wird. Diese Tabelle wird Überschriften haben, die den Translation Eigenschaften des Objekts entsprechen, und wir füllen sie direkt aus unserer _translations Sammlung.
<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>
Zum Index hinzufügen
Zum Schluss müssen Sie noch die TranslationComponent in die index.razor Datei hinzu. Dazu öffnen Sie Index.razor, entfernen Sie den Inhalt, außer der @page Richtlinie, und fügen Sie hinzu:
Konfigurieren Sie die App
Als Letztes müssen Sie die beiden Azure-Konfigurationselemente in die VonageDotnetTranslation.Server/appsettings.json Datei hinzu. Fügen Sie dem Basisobjekt zwei Felder hinzu, SUBSCRIPTION_KEY und REGIONund setzen Sie sie auf Ihren Abonnementschlüssel und Ihre Region.
Test
Das ist alles, was Sie tun müssen, um Ihren Sprachübersetzer zu erstellen! Jetzt müssen Sie ihn nur noch testen, indem Sie die App aus dem VonageDotnetTranslation/Server Verzeichnis mit dotnet run oder verwenden Sie f5 oder die Play-Taste.
Hinweis - Wenn Sie IIS Express verwenden, müssen Sie unsere Anleitung zur Verwendung von ngrok mit IIS Express
In unserem VoiceController haben wir die Übersetzungssprache auf Spanisch und die gesprochene Sprache auf US-Englisch eingestellt - Sie können dies leicht ändern - siehe die Unterstützte Sprachen welche Sprachen Azure unterstützt.
Weiter vorantreiben
Die WebSockets ermöglichen in Kombination mit den Azure Cognitive Services eine Vielzahl von leistungsstarken Anwendungsfällen. Neben Übersetzungen können Sie auch normale Transkriptionen oder sogar Stimmungsanalysen durchführen! Die Vonage-APIs ermöglichen alle Arten von hochflexiblen und relativ einfach zu erstellenden Integrationen mit PSTN und VoIP.
Ressourcen
Der Quellcode für diese Demo ist in GitHub
