
Teilen Sie:
Ehemaliger .NET Developer Advocate @Vonage, polyglotter Software-Ingenieur, AI/ML
Aufbau eines .NET-Transkriptionsdienstes in Echtzeit
Lesedauer: 4 Minuten
Der Aufbau von Sprache-zu-Text-Transkriptionsdiensten war noch nie so einfach. In dieser Demo werden Sie einen extrem einfachen, aber leistungsstarken Echtzeit-Transkriptionsdienst in ASP.NET erstellen, der das Vonage .NET SDK und Microsoft Azure's Sprach-SDK.
Voraussetzungen
Visual Studio 2019 Version 16.3 oder höher
Ein Azure Account
Fakultativ: Ngrok für den Testeinsatz
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.
In diesem Lernprogramm wird auch eine virtuelle Telefonnummer verwendet. Um eine zu erwerben, gehen Sie zu Rufnummern > Rufnummern kaufen und suchen Sie nach einer Nummer, die Ihren Anforderungen entspricht.
Azure Cognitive Services Ressource erstellen
Gehen Sie zu Ihrem Azure Dashboard
Öffnen Sie das Hamburger-Menü und wählen Sie "Ressource erstellen".
Suchen Sie nach Sprache und erstellen Sie eine Sprachressource:

Füllen Sie das Erstellungsformular aus. Zu Demonstrationszwecken können Sie die folgenden Eingaben verwenden
Name: TranscriptionTest
Abonnement: umlagefinanziert
Standort: Osten der USA
Preisstufe: F0
Ressourcengruppe: Transkription
Das Hochfahren wird einige Zeit in Anspruch nehmen. Sobald die Anwendung gestartet ist, navigieren Sie zum Abschnitt Schnellstart, um Ihre Zugangsschlüssel zu sammeln. Sie suchen nach dem Key1 Wert, also suchen Sie nach dem hervorgehobenen Abschnitt:

Speichern Sie diesen Schlüsselwert vorerst offline irgendwo.
Aufbau des Transkriptionsdienstes in Echtzeit
Projekt einrichten
Öffnen Sie Visual Studio und erstellen Sie ein neues Projekt ASP.NET Core WebApplication. Zum Beispiel: "TranscriptionBlogPostDemo".
Für diese Demonstration werden Sie nun eine MVC-Webanwendung in ASP.NET Core 3.0 erstellen.

Fügen Sie nun die folgenden Nuget-Pakete zum Projekt hinzu:
Nexmo.Csharp.Client
Newtonsoft.Json
Microsoft.CognitiveServices.Speech
Transkriptionsmaschine
Erstellen Sie mit diesen importierten Projekten eine neue Klasse namens TranscriptionEngine.
Definieren Sie zunächst einige Konstanten, die sowohl für das Sprach-SDK als auch für die Verwaltung des WebSocket-Puffers nützlich sind.
const int SAMPLES_PER_SECOND = 8000;
const int BITS_PER_SAMPLE = 16;
const int NUMBER_OF_CHANNELS = 1;
const int BUFFER_SIZE = 160 * 2;Fügen Sie dann der Klasse das folgende Feld hinzu:
_config - hier werden die Abonnement-/Regionalinformationen des Sprachanalysators gespeichert. Die Region in der Demo ist eastus - abgeleitet von der Region, für die Sie Ihren Sprachdienst konfiguriert haben. Für eine Zuordnung von Region zu Eingabe-String siehe die Microsoft Azure Speech Service Supported Regions Dokumentation
_inputStream - dies wird ein Push-Stream sein, der als Puffer dient, der zum Azure Speech-to-Text-Dienst gestreamt wird
_audioInput - dies wird die Eingabe für den Spracherkenner sein
_recognizer - dies ist der Erkenner, der die Spracherkennungsaufgabe durchführen wird
Diese können wie folgt definiert werden:
SpeechConfig _config = SpeechConfig.FromSubscription("your_subscription_key", "your_azure_region"); // e.g. eastus
PushAudioInputStream _inputStream = AudioInputStream.CreatePushStream(AudioStreamFormat.GetWaveFormatPCM(SAMPLES_PER_SECOND, BITS_PER_SAMPLE, NUMBER_OF_CHANNELS));
AudioConfig _audioInput;
SpeechRecognizer _recognizer;Da einige der Felder IDisposable sind, sollte diese Klasse IDisposable implementieren und alle Einwegfelder auf ihrem Weg nach unten einfach entsorgen
public void Dispose()
{
_inputStream.Dispose();
_audioInput.Dispose();
_recognizer.Dispose();
}Fügen Sie dann einen Konstruktor hinzu, der _audioInput mit dem oben definierten Push-Input-Stream initialisiert:
public TranscriptionEngine()
{
_audioInput = AudioConfig.FromStreamInput(_inputStream);
}Fügen Sie als Nächstes die Methode hinzu, die auf Spracherkennungsereignisse des Erkenners wartet
private void RecognizerRecognized(object sender, SpeechRecognitionEventArgs e)
{
Trace.WriteLine("Recognized: " + e.Result.Text);
}Von hier aus können Sie eine Funktion zum Anhalten und Starten des Spracherkenners hinzufügen.
Die Methode start Methode akzeptiert eine Sprachzeichenkette, setzt die Sprache der SpeechConfig, initialisiert den Recognizer mit der Konfiguration und der Audioeingabequelle, registriert das zuvor erstellte Ereignis RecognizerRecognized und startet eine kontinuierliche Erkennung.
Ihre stop Methode hebt die Registrierung des Ereignisses RecognizerRecognized auf und stoppt den Erkenner.
HINWEIS: Der StopContinuousRecognitionAsync kann bis zu 20 Sekunden dauern, da es derzeit keinen Mechanismus zum Abbrechen des laufenden Eingabestroms gibt. In dieser Demo wird dieses Problem explizit entschärft, indem der Recognizer zwischen den Aufrufen nicht wiederverwendet wird und das Herunterfahren des Sockets nicht blockiert wird, um den Vorgang abzuschließen.
public async Task StartSpeechTranscriptionEngine(string language)
{
_config.SpeechRecognitionLanguage = language;
_recognizer = new SpeechRecognizer(_config, _audioInput);
_recognizer.Recognized += RecognizerRecognized;
await _recognizer.StartContinuousRecognitionAsync();
}
private async Task StopTranscriptionEngine()
{
if(_recognizer != null)
{
_recognizer.Recognized -= RecognizerRecognized;
await _recognizer.StopContinuousRecognitionAsync();
}
}Die letzte Aufgabe, die diese Klasse übernehmen wird, ist der Empfang von Audiodaten über den Websocket, den Sie einrichten werden, und deren Weiterleitung an den zuvor erstellten PushAudioStream. Dies wird erwartet, nachdem der Websocket eingerichtet wurde, und zwar so lange, bis der Websocket geschlossen wird.
public async Task ReceiveAudioOnWebSocket(HttpContext context, WebSocket webSocket)
{
var buffer = new byte[BUFFER_SIZE];
try
{
var language = "en-US";
await StartSpeechTranscriptionEngine(language);
WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
while (!result.CloseStatus.HasValue)
{
await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.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();
}
}HINWEIS: Der anfängliche Puffer, den Sie vom Websocket zurückerhalten, enthält Metadaten für den Aufruf. Wenn Sie möchten, können Sie diese Daten aus dem ersten ReceiveAsync extrahieren - für die Zwecke der Demo wird dies jedoch nicht getan, da der Puffer und der Recognizer robust genug sind, um damit umzugehen.
Einrichten von WebSockets in Ihrer Anwendung
Öffnen Sie Startup.cs.
In der Configure-Methode werden Sie Websockets auf dem Server aktivieren und ein Stück Websocket-Middleware bereitstellen, um Websockets zu verwenden und einen eingehenden Websocket zu verbinden und die TranscriptionEngine zu verwenden, um Audio über diesen Socket zu empfangen.
var webSocketOptions = new WebSocketOptions()
{
KeepAliveInterval = TimeSpan.FromSeconds(120),
ReceiveBufferSize = 320
};
app.UseWebSockets(webSocketOptions);
app.Use(async (context, next) =>
{
if (context.Request.Path == "/ws")
{
if (context.WebSockets.IsWebSocketRequest)
{
WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
using (var engine = new TranscriptionEngine())
{
await engine.ReceiveAudioOnWebSocket(context, webSocket);
}
}
else
{
context.Response.StatusCode = 400;
}
}
else
{
await next();
}
});
Einrichten des Voice Controllers
Der letzte Teil des Codes, der implementiert werden muss, ist das Hinzufügen eines Voice Controllers. Fügen Sie einen neuen Controller unter der Datei Controller hinzu und nennen Sie ihn VoiceController. Fügen Sie eine konstante Zeichenfolge für die BASE_URL Ihres Dienstes hinzu.
const string BASE_URL = "BASE_URL";Ihr Voice Controller wird zwei HTTP-Anfragen haben. Eine POST-Anfrage für den Ereignis-Webhook und eine GET-Anfrage für den Antwort-Webhook. Diese GET-Anfrage wird eine NCCO mit einer einzigen Connect-Aktion erstellen, die die Voice API anweist, einen WebSocket zu Ihrem Server zu öffnen und den Audiostrom über diesen Socket zurückzuschicken. Stellen Sie den Inhaltstyp auf ein lineares 16-Bit-PCM mit 8 kHz ein. Siehe unten:
[HttpPost]
public HttpStatusCode Events()
{
return HttpStatusCode.OK;
}
[HttpGet]
public string Answer()
{
var webSocketAction = new ConnectAction()
{
Endpoint = new[]
{
new WebsocketEndpoint()
{
Uri = $"wss://{BASE_URL}/ws",
ContentType="audio/l16;rate=8000",
}
}
};
var ncco = new Ncco(webSocketAction);
return ncco.ToString();
} Einrichten und loslegen
Einrichten von IIS Express
Öffnen Sie den Eigenschaften-Dialog für Ihr Projekt, notieren Sie sich unter Debug die Portnummer - für die Demo deaktivieren Sie SSL, das erleichtert die Einrichtung von ngrok.
Einrichtung des Ngrok-Tunnels
Damit die Voice API die Ereignis-/Antwort-Webhooks weiterleiten kann, müssen Sie die Site dem Internet aussetzen - zu Testzwecken können Sie ngrok verwenden, um unseren IIS-Express-Port freizugeben. Öffnen Sie Ihre Befehlszeile und verwenden Sie diesen Befehl, ersetzen Sie PORT_NUMBER durch die Portnummer Ihrer IIS-Express-Instanz.
ngrok http --host-header="localhost:PORT_NUMBER" http://localhost:PORT_NUMBER
Dieser Befehl erzeugt eine Ausgabe wie diese:

Einrichten der Vonage Voice-Anwendung
Der nächste Schritt ist das Einrichten einer Vonage Voice Application.
Navigieren Sie zu Ihrem Vonage Dashboard
Öffnen Sie im linken Bereich Voice und klicken Sie auf "Eine Anwendung erstellen".
Benennen Sie die Anwendung, z. B. 'TranscriptionTest'.
Unter Funktionen Voice aktivieren
Für Ereignis-URL hinzufügen base_url_of_ngrok_tunnel/voice/events
Für Antwort-URL base_url_of_ngrok_tunnel/voice/answer hinzufügen
Für Fallback-Antwort-URL base_url_of_ngrok_tunnel/voice/answer hinzufügen
Letzte Handgriffe
Jetzt, wo du die ngrok-URL hast, ändere die BASE_URL in der VoiceController-Datei in diese URL (ohne das 'http://')
Damit sind Sie startklar. Rufen Sie die mit Ihrer Anwendung verknüpfte Vonage-Nummer an, und die App überträgt Ihre Sprache auf die Debug-Konsole.
