
Share:
)
Adam ist ein Entwickler und Berater, der gerne Ultraläufe absolviert, bloggt und anderen dabei hilft, Technologien zu zähmen, um erstaunliche Dinge zu erreichen, und der ein unstillbares Verlangen hat, Mentoren zu sein und zu helfen.
AWS Transcribe mit Nexmo Voice unter Verwendung von PHP
Lesedauer: 13 Minuten
Anwendungsfälle für die Sprachtranskription werden immer häufiger - von IoT-Geräten, die oft nur über eine Audioschnittstelle verfügen, bis hin zu Sprachnachrichtendiensten, von denen erwartet wird, dass sie eine Echtzeit-Textvorschau des Nachrichteninhalts liefern, werden Sprache-zu-Text-Funktionen für eine Vielzahl von Anwendungen unverzichtbar.
In diesem Tutorial verwenden wir eine Nexmo Voice Nummer, um ein Rückrufskript zu erstellen, das mit einem Anrufer interagiert und ihn zur Eingabe einer Sprachnachricht auffordert. Nachdem wir den Inhalt der Aufnahme abgerufen haben, werden wir eine Sprachtranskription von Amazon Transcribe.
Voraussetzungen
In diesem Beispiel werden die folgenden Angaben benötigt:
PHP lokal installiert (Version 7.3+ bevorzugt)
Composer installiert global (weitere Einzelheiten später)
AWS Konto
ngrok lokal installiert (mehr dazu später)
Ein vollständiges Codebeispiel finden Sie unter https://github.com/nexmo-community/voice-aws-speechtotext-php.
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.
AWS-Einrichtung
Sie benötigen ein AWS-Konto, sowie IAM-Anmeldeinformationen die mit einem Benutzer verbunden sind, der Zugriff hat auf Amazon Transcribe und AWS S3.
Ein S3 Bucket erstellen
Erstellen Sie ein S3 Bucket, um die von Nexmo abgerufenen MP3-Dateien der Sprachaufnahmen zu speichern. Dies ermöglicht Amazon Transcribe den einfachen Zugriff auf die Dateien, um sie später zu transkribieren.
Aktivieren Sie nach der Erstellung des Bereichs das Kontrollkästchen neben dem Bereichsnamen. Dadurch wird ein Feld von rechts eingeblendet. Klicken Sie auf die Schaltfläche "Copy Bucket ARN" und speichern Sie sie zur späteren Verwendung.
Erstellen eines IAM-Benutzers
Wählen Sie die IAM-Verwaltungskonsole im Bereich Dienste aus:
Select IAM Management Console
Fügen Sie in der IAM-Verwaltungskonsole einen neuen IAM-Benutzer hinzu, indem Sie auf die blaue Schaltfläche Benutzer hinzufügen klicken:
Add a new IAM user
Nachfolgend finden Sie ein JSON-Snippet, mit dem Sie dem neuen Benutzer die erforderlichen Berechtigungen für die Nutzung von S3 und der Transcribe-Dienste zuweisen können. Stellen Sie sicher, dass Sie {bucket_name}
durch den tatsächlichen Bucket-Namen ersetzen. Die Resource
im JSON sollte mit dem ARN übereinstimmen, den Sie nach der Erstellung des Buckets in S3 gespeichert haben:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "transcribe:*",
"Resource": "*"
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::{bucket_name}/*"
}
]
}
Anwendung Basis
An diesem Punkt müssen wir mit der Organisation der Anwendung selbst beginnen. Wir gehen von einem leeren Verzeichnis aus und beginnen von dort aus mit der Erstellung der Beispiel-Callback-Anwendung. Außerdem gehen wir von einem lokalen System aus, auf dem PHP bereits eingerichtet ist und läuft und über die Befehlszeilenschnittstelle (CLI) verwendet werden kann.
Erstellen Sie in diesem leeren Verzeichnis eine neue PHP-Datei und nennen Sie sie index.php
. Im Moment geben Sie einfach das Wort "test" in die Datei ein. Dies wird eine Ausgabe erzeugen und uns ermöglichen, im nächsten Schritt zu testen.
PHP Eingebauter Webserver und ngrok
In diesem Beispiel führen wir eine PHP-Anwendung lokal mit dem PHP eingebauten Webserver. Obwohl der integrierte Webserver nicht in einer Produktionsumgebung verwendet werden sollte, ist er für Beispielskripte wie dieses gut geeignet.
Wechseln Sie mit einem Terminal in das Projektverzeichnis. Geben Sie dort den Befehl zum Starten des integrierten PHP-Webservers wie folgt ein:
Jetzt sollte die Eingabe von "http://localhost:8080" in einem Browser eine "Test"-Antwort ergeben, wenn Sie dies in der index.php
Datei eingegeben haben.
Wir verwenden auch ngrok um die lokale Anwendung im Internet als Callback-Endpunkt für den Nexmo-Voice-Dienst verfügbar zu machen. Werfen Sie einen Blick auf diese Seite wenn Sie Hilfe bei der Einrichtung von ngrok benötigen, aber die Grundlagen sind: Erstellen Sie ein Konto bei ngrok, laden Sie die ausführbare Datei herunter, starten Sie einen Tunnel per CLI und verwenden Sie dann die vom CLI bereitgestellten Weiterleitungs-URLs.
Als Nächstes bringen Sie ngrok zum Laufen, um die Ergebnisse des Webservers über das Internet verfügbar zu machen. Navigieren Sie in einem Terminal zu dem Ort, an dem ngrok zuvor installiert wurde, und geben Sie den folgenden Befehl ein:
Im Gegenzug stellt uns ngrok einige wichtige Informationen zur Verfügung, wie auf dem folgenden Screenshot zu sehen ist:
ngrok information returned
Auf diese Weise erhalten wir die Informationen über den Dienst, einschließlich der Tunnel-URLs, mit denen wir unser lokal ausgeführtes Skript aufrufen können. Wir können die bereitgestellten Informationen in einen Webbrowser eingeben und sollten die gleichen Ergebnisse erhalten wie bei der obigen Abfrage über localhost.
Hinweis: Es wird empfohlen, https-URLs zu verwenden, um alle zwischen den Diensten ausgetauschten Anmeldeinformationen zu schützen.
Wir werden die ngrok-Instanz während dieses Beispiels laufen lassen. Wenn Sie bereit sind, es zu beenden, drücken Sie einfach "Strg+c" im Terminal und es wird ngrok geschlossen.
Nexmo-Einrichtung
Mit den von ngrok bereitgestellten URLs können wir eine Anwendung in Nexmo hinzufügen und sie mit einer Nummer verknüpfen. Erweitern Sie im Nexmo Dashboard den Menüpunkt Nummern, um "Ihre Nummern" anzuzeigen (und fügen Sie bei Bedarf eine neue Nummer hinzu):
Nexmo Dashboard
Da wir nun sicher sind, dass es eine Nummer gibt, die in einer Anwendung verwendet werden soll, klicken Sie im linken Menü auf "Ihre Anwendungen" und dann auf "Eine neue Anwendung erstellen":
Create Application
Geben Sie der Anwendung einen guten Namen, klicken Sie dann auf die Schaltfläche zum Erzeugen eines öffentlichen und privaten Schlüssels im Bereich Authentifizierung und speichern Sie die private.key
in dem oben neu erstellten App-Verzeichnis:
Authentication Keys
Schalten Sie die Sprachfunktion ein und fügen Sie die von ngrok oben angegebene URL in die Felder ein:
Voice URLs
Dies weist Nexmo an, Rückrufe zu tätigen, wenn bestimmte Ereignisse eintreten, und wir wollen, dass diese Rückrufe auf die neue App verweisen, die wir erstellen werden.
Die Ereignis-URL wird verwendet, wenn ein Ereignis den Status eines Anrufs ändert, während die Antwort-URL für alle eingehenden Anrufe angefordert wird, um ein NCCO-Objekt abzurufen (Nexmo Anrufsteuerungsobjekt).
Klicken Sie abschließend unten auf die Schaltfläche "Neuen Antrag erstellen".
Nur noch ein weiterer Schritt, um sicherzustellen, dass diese neue Anwendung wie erwartet funktioniert. Klicken Sie auf der Seite Ihre Anwendungen auf die neu erstellte Anwendung. Unten auf der Seite finden Sie eine Liste der verfügbaren Nummern im Konto. Klicken Sie auf die Schaltfläche "Verknüpfen", um die Anwendung mit der gewünschten Nummer zu verknüpfen:
Link the app
Jetzt sind wir mit der Einrichtung von Nexmo fertig. Zeit, mit der Entwicklung der App zu beginnen!
Komponist
Im Projektordner müssen wir Composer starten, damit wir einige Pakete/Abhängigkeiten einbinden können. Navigieren Sie zum Projektverzeichnis und geben Sie den folgenden Befehl ein:
Die neuesten Versionen von Composer führen nun einen schrittweisen Prozess durch, um Ihnen bei der Einrichtung eines Projekts zu helfen. Folgen Sie den Eingabeaufforderungen und füllen Sie die Felder wie gewünscht aus. Stellen Sie sicher, dass Sie diese Pakete einschließen:
Erforderliche Abhängigkeiten
Um den Assistenten aus dem vorigen Abschnitt zu vervollständigen oder manuell eine composer.json
Datei zu erstellen, schließen Sie die folgenden Abhängigkeiten für dieses Beispiel ein:
vlucas/phpdotenv - speichert Anmeldeinformationen in der superglobalen Datei $_ENV
schlank/slim - leichtes Microframework, das den Umgang mit HTTP-Aufrufen und Rückrufen erleichtert
slim/psr7 - erleichtert die HTTP-Interoperabilität zwischen Bibliotheken
nexmo/client - für alles, was mit Nexmo zu tun hat, was auch Guzzle als Abhängigkeit einbringt
league/flysystem-aws-s3-v3 - um die Nutzung von S3 zu abstrahieren, was auch das AWS SDK als Abhängigkeit einbringt
Abgeschlossen composer.json
Beispiel:
{
"require": {
"ext-json": "used for JSON handling",
"slim/slim": "4.2.0",
"slim/psr7": "0.5",
"vlucas/phpdotenv": "3.5.x-dev",
"nexmo/client": "2.0.0",
"league/flysystem-aws-s3-v3": "1.0.23"
}
}
Composer-Installation
Nachdem alle Abhängigkeiten zu Composer hinzugefügt wurden, können wir sie nun mit dem folgenden Befehl in der CLI installieren:
Berechtigungsnachweise hinzufügen
Die Zugangsdaten für diese Beispielanwendung werden in einer ENV-Datei gespeichert und von phpdotenv geparst.
ENV-Einrichtung
Das Erstellen einer .env
Datei ermöglicht es uns, Anmeldeinformationen zu speichern, die für die Verbindung mit externen Diensten wie Nexmo und AWS benötigt werden. Fügen Sie den folgenden Inhalt in eine neu erstellte .env
Datei im Stammverzeichnis des Projekts hinzu:
HINWEIS: Die oben genannten Informationen können sich ändern. Prüfen Sie daher die Einstellungen bei AWS bzw. Nexmo.
PHPDotEnv Verwendung
In der Datei index.php
fügen Sie den folgenden Code ein, um den Composer Autoloader zu nutzen und das PHP-Paket phpdotenv zu verwenden, um den Inhalt der Datei .env
Datei in die superglobale Datei $_ENV einzufügen:
<?php
require('vendor/autoload.php');
Dotenv\Dotenv::create(__DIR__)->load();
Slim PHP verwenden
Um slim in unserem Beispiel-Callback-Skript einzurichten, importieren wir mit einer use
Anweisung importieren, unmittelbar nach dem Composer Autoload require
. Dann rufen wir die create()
Funktion von Slim auf, um eine Slim-App zu erstellen und einen Funktionsaufruf an app->run
am Ende der Datei, um die Dinge in Gang zu setzen:
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
use Slim\Factory\AppFactory;
$app = AppFactory::create();
//... call to Dotenv::create() shown earlier
//... we will create additional route-based middleware here
$app->run();
Hinzufügen von Abhängigkeiten
Es sind noch einige weitere Abhängigkeiten erforderlich, um unsere Arbeit zu erleichtern, also fügen wir unserem Skript die folgenden Importe hinzu. Damit stellen wir sicher, dass die benötigten Klassen für den Composer-Autoloader verfügbar sind:
use Nexmo\Client;
use Nexmo\Client\Credentials\Keypair;
use Aws\S3\S3Client;
use League\Flysystem\AwsS3v3\AwsS3Adapter;
use League\Flysystem\Filesystem;
use Aws\TranscribeService\TranscribeServiceClient;
Status-Updates
Wie bereits erwähnt, wird Nexmo bei so gut wie jedem Ereignis Status-Updates senden. Lassen Sie uns also zuerst diese routenbasierte Middleware aufbauen, um sie aus dem Weg zu räumen:
$app->post('/webhooks/event', function (Request $request, Response $response) {
$params = $request->getParsedBody();
error_log($params['recording_url']);
return $response
->withStatus(204);
});
Diese routenbasierte Middleware empfängt einfach eine Anfrage an /webhooks/event
und protokolliert sie. Mehr wird für dieses Beispiel nicht benötigt.
Antwort auf einen Anruf
Wir möchten die Slim-Funktionalität nutzen, um HTTP-Anfragen an unseren /webhooks/answer
Endpunkt unter Verwendung einer routenbasierten Middleware abzufangen, so dass wir, wenn Nexmo einen Anruf an unsere (zuvor konfigurierte) Nummer erhält, eine JSON-Antwort bereitstellen können. Konkret wollen wir Nexmo eine NCCO-Nutzlast zur Verfügung stellen.
So sieht diese Middleware aus:
$app->any('/webhooks/answer', function (Request $request, Response $response) {
$uri = $request->getUri();
if ($request->getMethod() != 'GET') {
return $response->withStatus(403);
}
$ncco = [
[
'action' => 'talk',
'text' => 'Please leave a message after the tone, then press #.'
],
[
'action' => 'record',
'eventUrl' => [
$uri->getScheme().'://'.$uri->getHost().'/webhooks/fetch'
],
'endOnSilence' => '3',
'endOnKey' => '#',
'beepOnStart' => true
],
[
'action' => 'talk',
'text' => 'Thank you for your message. Goodbye.'
],
[
'action' => 'notify',
'payload' => ['followup' => true],
'eventUrl' => [
$uri->getScheme().'://'.$uri->getHost().'/webhooks/transcribe'
],
'eventMethod' => "POST"
],
];
$response->getBody()->write(json_encode($ncco));
return $response
->withHeader('Content-Type', 'application/json');
});
Mit dieser routenbasierten Middleware reagiert die App auf eine GET HTTP-Anfrage an /webhooks/answer
mit einem NCCO-Objekt, das Nexmo anweist, den Anruf zu beantworten, indem es nach einer Nachricht fragt und den Anrufer auffordert, die #-Taste zu drücken, um den Anruf zu beenden.
Nach der Aufnahme, die entweder durch eine 3-sekündige Stille oder durch Drücken der #-Taste beendet wird, sollte Nexmo einen Rückruf an den /webhooks/fetch
Endpunkt machen, der die MP3-Abfrage der Aufnahme startet und sich beim Anrufer für die Nachricht bedankt.
Und schließlich, sobald der Rückruf in der Aufnahme abgeschlossen ist, wird Nexmo einen Benachrichtigungsrückruf an den /webhooks/transcribe
Endpunkt, um Amazon Transcribe zu starten.
Aufnahmen holen
Wenn eine Sprachaufnahme gemacht wird, wird sie bei Nexmo zum Abruf gespeichert. Daher müssen wir eine routenbasierte Middleware erstellen, die von Nexmo aufgerufen wird, um den Download zu initiieren. Sie wird wie folgt aussehen:
$app->post('/webhooks/fetch', function (Request $request, Response $response) {
$params = json_decode($request->getBody(), true);
// Create Nexmo Client
$keypair = new Keypair(
file_get_contents($_ENV['NEXMO_APPLICATION_PRIVATE_KEY_PATH']),
$_ENV['NEXMO_APPLICATION_ID']
);
$nexmoClient = new Client($keypair);
$data = $nexmoClient->get($params['recording_url']);
// Create AWS S3 Client
$S3Client = new S3Client([
'region' => $_ENV['AWS_REGION'],
'version' => 'latest',
]);
$adapter = new AwsS3Adapter($S3Client, $_ENV['AWS_S3_BUCKET_NAME']);
$filesystem = new Filesystem($adapter);
$filesystem->put('/' . $_ENV['AWS_S3_RECORDING_FOLDER_NAME'] .'/'.$params['conversation_uuid'].'.mp3', $data->getBody());
return $response
->withStatus(204);
});
Im Beispielcode dekodieren wir das JSON aus dem Request Body, um die URL der Aufzeichnung zu erhalten. Dann erstellen wir einen Client des Nexmo SDK (unter Verwendung eines Schlüsselpaares für die Anmeldedaten) und rufen die Aufnahme ab.
Anschließend leiten wir die Aufzeichnung an AWS S3 weiter, indem wir FlySystemund nutzen das AWS SDK für die Konnektivität.
umschreiben.
Der letzte Schritt besteht darin, die routenbasierte Middleware zu erstellen, um die Transkription durch den Amazon Transcribe Dienst anzufordern. Hier ist, wie man das macht:
$app->post('/webhooks/transcribe', function (Request $request, Response $response) {
$params = json_decode($request->getBody(), true);
// Create Amazon Transcribe Client
$awsTranscribeClient = new TranscribeServiceClient([
'region' => $_ENV['AWS_REGION'],
'version' => 'latest',
]);
$transcriptionResult = $awsTranscribeClient->startTranscriptionJob([
'LanguageCode' => 'en-US',
'Media' => [
'MediaFileUri' => 'https://' . $_ENV['AWS_S3_BUCKET_NAME'] . '.s3.amazonaws.com/' . $_ENV['AWS_S3_RECORDING_FOLDER_NAME'] . '/' . $params['conversation_uuid'] . '.mp3',
],
'MediaFormat' => 'mp3',
'TranscriptionJobName' => 'nexmo_voice_' . $params['conversation_uuid'],
]);
$response->getBody()->write(json_encode($transcriptionResult->toArray()));
return $response
->withHeader('Content-Type', 'application/json')
->withStatus(204);
});
Hinweis: Das AWS SDK erhält die Anmeldung und den Schlüssel von der Umgebung.
In dieser Middleware wird die JSON-Nutzlast in der Anfrage geparst, damit wir die conversation_uuid
.
Dann wird ein Amazon Transcribe-Client verwendet, um einen Transkriptionsauftrag unter Verwendung der auf S3 gespeicherten MP3-Datei zu erstellen.
Schlussfolgerung
Anhand dieses Beispiels konnten wir einen Anruf an eine Nexmo-Nummer entgegennehmen, den Anrufer auffordern, eine Nachricht zu hinterlassen, die Nachricht im MP3-Format abrufen und auf AWS S3 speichern und dann Amazon Transcribe auffordern, die Sprache in Text umzuwandeln.
Von dort aus kann der Text über die AWS-Konsole von AWS Transcribe abgerufen werden. Vielleicht können wir auch eine Art geplante Aufgabe erstellen, die in regelmäßigen Abständen überprüft, bevor sie für andere Zwecke heruntergeladen wird.
Ein vollständiges Codebeispiel finden Sie unter https://github.com/nexmo-community/voice-aws-speechtotext-php.