https://d226lax1qjow5r.cloudfront.net/blog/blogposts/aws-transcribe-with-nexmo-voice-using-php-dr/E_Voice-Transcription-PHP_1200x600.png

AWS Transcribe avec Nexmo Voice en PHP

Publié le April 28, 2021

Temps de lecture : 14 minutes

Les cas d'utilisation de la transcription vocale sont de plus en plus répandus - des appareils IoT, qui ne disposent souvent que d'une interface audio, aux services de messagerie vocale, qui doivent fournir des aperçus textuels en temps réel du contenu des messages, les capacités de conversion de la parole en texte deviennent essentielles pour une grande variété d'applications.

Dans ce tutoriel, nous utiliserons un appareil de Nexmo Voice pour créer un script de rappel qui interagit avec un appelant pour lui demander un message vocal. Puis, après avoir récupéré le contenu de l'enregistrement, nous demanderons une transcription vocale à Amazon Transcribe.

Conditions préalables

Dans cet exemple, les éléments suivants sont nécessaires :

  • PHP installé localement (version 7.3+ de préférence)

  • Composer installé globalement (plus de détails ultérieurement)

  • AWS Account

  • ngrok installé localement (plus de détails plus tard)

Pour un exemple de code complet, voir https://github.com/nexmo-community/voice-aws-speechtotext-php.

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.

Configuration d'AWS

Vous aurez besoin d'un Account AWS, ainsi que de informations d'identification IAM associés à un utilisateur ayant accès à Amazon Transcribe et à AWS S3.

Création d'un Bucket S3

Créez un Bucket S3 pour stocker les fichiers MP3 d'enregistrement vocal récupérés auprès de Nexmo. Cela permettra à Amazon Transcribe d'accéder facilement aux fichiers à transcrire ultérieurement.

Après l'avoir créé, veillez à cocher la case située à côté du nom du seau. Cela entraînera le déplacement d'un panneau vers la droite. Cliquez sur le bouton "Copy Bucket ARN" et sauvegardez-le pour une utilisation ultérieure.

Création d'un utilisateur IAM

Sélectionnez la console de gestion IAM dans le panneau Services :

Select IAM Management ConsoleSelect IAM Management Console

Dans la console de gestion IAM, ajoutez un nouvel utilisateur IAM en cliquant sur le bouton bleu Ajouter un utilisateur :

AWS new IAM userAdd a new IAM user

Vous trouverez ci-dessous un extrait JSON permettant d'attribuer les autorisations nécessaires pour que le nouvel utilisateur puisse utiliser S3 et les services Transcribe. Veillez à remplacer {bucket_name} par le nom de l'unité de stockage. Le Resource dans le JSON doit correspondre à l'ARN que vous avez sauvegardé depuis S3 après avoir créé le seau :

{
    "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}/*"
        }
    ]
}

Base d'applications

À ce stade, nous devons commencer à organiser l'application elle-même. Nous partirons d'un répertoire vide, et commencerons à construire l'exemple d'application de rappel à partir de là. Nous supposerons également que nous disposons d'un système local sur lequel PHP est déjà installé et fonctionne, et qu'il peut être utilisé via l'interface de ligne de commande (CLI).

Dans ce répertoire vide, créez un nouveau fichier PHP et nommez-le index.php. Pour l'instant, tapez simplement le mot "test" dans le fichier. Cela créera une sortie et nous permettra de tester dans l'étape suivante.

Serveur web intégré à PHP et ngrok

Dans cet exemple, nous allons exécuter une application PHP localement avec le serveur web intégré de PHP intégré au serveur web. Bien que le serveur web intégré ne doive pas être utilisé dans un environnement de production, il convient parfaitement pour des exemples de scripts comme celui-ci.

A l'aide d'un terminal, naviguez jusqu'au répertoire du projet. Une fois dans ce répertoire, lancez la commande pour démarrer le serveur web intégré PHP, comme suit :

php -S localhost:8080

À ce stade, la saisie de "http://localhost:8080" dans un navigateur devrait produire une réponse "test", si c'est ce que vous avez saisi dans le fichier index.php si c'est ce que vous avez saisi dans le fichier

Nous utiliserons également ngrok pour rendre l'application locale disponible sur Internet en tant que point de rappel pour le service Nexmo Voice. Jetez un coup d'œil à cette page si vous avez besoin d'aide pour configurer ngrok, mais les bases sont les suivantes : créer un Account sur ngrok, télécharger l'exécutable, démarrer un tunnel via le CLI, et ensuite utiliser les URLs de redirection fournies par le CLI.

Ensuite, lancez ngrok pour rendre les résultats du serveur web disponibles sur internet. Dans un terminal, naviguez jusqu'à l'endroit où ngrok a été installé précédemment, et entrez la commande suivante :

./ngrok http 8080

En retour, ngrok nous fournira quelques informations importantes, comme dans la capture d'écran ci-dessous :

ngrok information returnedngrok information returned

Cela nous permet de connaître les informations relatives au service, y compris les URL de tunnel à utiliser pour accéder à notre script exécuté localement. Nous pouvons saisir les informations fournies dans un navigateur web et nous devrions obtenir les mêmes résultats que lors de la requête via localhost ci-dessus.

Remarque : il est recommandé d'utiliser des URL https pour protéger les informations d'identification partagées entre les services.

Nous laisserons l'instance de ngrok fonctionner tout au long de cet exemple. Lorsque vous serez prêt à l'arrêter, appuyez simplement sur "Ctrl+c" dans le terminal et ngrok se fermera.

Mise en place de Nexmo

Avec les URLs fournies par ngrok, nous pouvons ajouter une Applications dans Nexmo et la lier à un numéro. Dans le tableau de bord Nexmo, développez l'élément de menu Numbers pour exposer "Vos numéros" (et ajoutez-en un nouveau si nécessaire) :

nexmo_dashboardNexmo Dashboard

Maintenant que nous sommes sûrs qu'il y a un numéro à utiliser dans une application, dans le menu de gauche, cliquez sur "Vos applications" puis sur "Créer une nouvelle application" :

create_applicationCreate Application

Donnez un bon nom à l'application, puis cliquez sur le bouton pour générer une clé publique et une clé privée dans la zone Authentification, en sauvegardant les private.key dans le répertoire de l'application nouvellement créé ci-dessus :

authentication_keysAuthentication Keys

Activez la fonction Voice et ajoutez l'URL donnée par ngrok ci-dessus dans les champs :

voice_urlsVoice URLs

Cela demande à Nexmo de faire des rappels lorsque des événements spécifiques se produisent, et nous voulons que ces rappels pointent vers la nouvelle application que nous allons créer.

L'URL de l'événement sera utilisée lorsqu'un événement modifie le statut d'un appel, tandis que l'URL de la réponse est demandée pour tous les appels entrants afin de récupérer un objet NCCO (Nexmo Call Control Object).Objet de contrôle d'appel Nexmo).

Enfin, cliquez sur le bouton en bas pour "Générer une nouvelle application".

Il ne reste plus qu'une étape à franchir pour s'assurer que cette nouvelle application fonctionne comme prévu. Dans le tableau "Vos Applications", cliquez sur la nouvelle application créée. Vers le bas de la page, vous trouverez une liste des numéros disponibles sur le compte. Cliquez sur le bouton pour "lier" la demande au numéro souhaité :

link_the_appLink the app

Nous avons maintenant terminé l'installation de Nexmo. Il est temps de commencer à construire l'application !

Compositeur

Dans le dossier du projet, nous devons lancer Composer, ce qui nous permettra d'inclure quelques paquets/dépendances. Naviguez jusqu'au répertoire du projet et lancez la commande suivante.. :

composer init

Les dernières versions de Composer proposent désormais un processus étape par étape pour faciliter la mise en place d'un projet. Suivez les instructions et remplissez les champs comme vous le souhaitez. Veillez à inclure ces paquets :

Dépendances requises

Pour compléter l'assistant de la section précédente, ou pour configurer manuellement un fichier composer.json inclure les dépendances suivantes pour cet exemple :

  • vlucas/phpdotenv - stocke les informations d'identification dans la superglobale $_ENV

  • slim/slim - micro-cadre léger qui facilite la gestion des appels HTTP et des callbacks

  • slim/psr7 - facilite l'interopérabilité HTTP entre les bibliothèques

  • nexmo/client - pour tout ce qui concerne Nexmo, qui apportera également Guzzle comme dépendance

  • league/flysystem-aws-s3-v3 - pour abstraire l'utilisation de S3, qui apportera également le SDK AWS en tant que dépendance

Terminé composer.json exemple :

{
    "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"
    }
}

Installation de Composer

Avec toutes les dépendances ajoutées à Composer, nous sommes maintenant prêts à les installer en utilisant la commande suivante dans le CLI :

composer install

Ajout d'informations d'identification

Les informations d'identification pour cet exemple d'application seront placées dans un fichier ENV et analysées par phpdotenv.

Configuration de l'ENV

La création d'un fichier .env nous permet de stocker les informations d'identification nécessaires à la connexion à des services externes, tels que Nexmo et AWS. Ajoutez le contenu suivant à un fichier .env nouvellement créé à la racine du projet :

APP_ID=voice-aws-transcribe-php LANG_CODE=en-US SAMPLE_RATE=8000 AWS_REGION= AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= AWS_S3_BUCKET_NAME= AWS_S3_RECORDING_FOLDER_NAME= NEXMO_APPLICATION_PRIVATE_KEY_PATH='./private.key' NEXMO_APPLICATION_ID=

NOTE : Les informations ci-dessus peuvent changer, assurez-vous donc de vérifier les paramètres chez AWS et Nexmo respectivement.

Utilisation de PHPDotEnv

Dans le fichier index.php créé précédemment, ajoutez le code suivant pour tirer parti de l'autoloader Composer et pour utiliser le paquetage PHP phpdotenv afin d'injecter le contenu du fichier .env dans la superglobale $_ENV :

<?php

require('vendor/autoload.php');

Dotenv\Dotenv::create(__DIR__)->load();

Utilisation de Slim PHP

Pour mettre en place slim dans notre exemple de script de rappel, nous allons importer avec une déclaration use immédiatement après l'autoload de Composer require. Ensuite, nous appellerons la fonction create() de Slim pour créer une application Slim et un appel de fonction à app->run à la fin du fichier pour donner le coup d'envoi :

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();

Ajout de dépendances

Quelques dépendances supplémentaires sont nécessaires pour nous faciliter la tâche, alors ajoutons les importations suivantes à notre script. Celles-ci nous permettront de nous assurer que les classes dont nous avons besoin sont disponibles pour l'autoloader de Composer :

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;

Mises à jour de l'état d'avancement

Comme nous l'avons dit plus haut, Nexmo enverra des mises à jour de statut sur pratiquement tous les événements. Donc, construisons d'abord ce middleware basé sur les routes pour l'écarter de notre chemin :

$app->post('/webhooks/event', function (Request $request, Response $response) {

    $params = $request->getParsedBody();

    error_log($params['recording_url']);

    return $response
        ->withStatus(204);
});

Cet intergiciel basé sur les itinéraires reçoit simplement une demande à l'adresse /webhooks/event et l'enregistre. Rien de plus n'est nécessaire pour cet exemple.

Répondre à un appel

Nous voulons utiliser la fonctionnalité Slim pour capturer les requêtes HTTP vers notre point de terminaison à l'aide d'un middleware basé sur les routes. /webhooks/answer à l'aide d'un middleware basé sur les routes, de sorte que, lorsque Nexmo reçoit un appel vers notre numéro (configuré précédemment), nous puissions fournir une réponse JSON. Plus précisément, nous voulons fournir à Nexmo une charge utile NCCO.

Voici à quoi ressemble cet intergiciel :

$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');
});

Avec cet intergiciel basé sur les routes, l'application répondra à une requête HTTP GET vers /webhooks/answer avec un objet NCCO indiquant à Nexmo de répondre à l'appel en demandant un message et en demandant à l'appelant d'appuyer sur la touche # pour mettre fin à l'appel.

Après l'enregistrement, qui se termine soit par un silence de 3 secondes, soit par l'appui de l'appelant sur la touche #, Nexmo doit alors effectuer un rappel vers le point de terminaison /webhooks/fetch qui lance la récupération de l'enregistrement au format MP3 et remercie l'appelant pour son message.

Et enfin, une fois que le rappel dans l'enregistrement est terminé, Nexmo effectuera un rappel de notification au point de terminaison /webhooks/transcribe pour lancer Amazon Transcribe.

Fetch Recordings

Lorsqu'un enregistrement vocal est effectué, il est stocké chez Nexmo pour être récupéré. Nous devons donc créer un intergiciel basé sur une route qui sera appelé par Nexmo pour lancer le téléchargement. Il se présentera comme suit :

$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);
});

Dans l'exemple de code, nous décodons le JSON du corps de la requête pour obtenir l'URL de l'enregistrement. Ensuite, nous créons un client du Nexmo SDK (en utilisant une paire de clés pour les informations d'identification) et récupérons l'enregistrement.

Nous transmettons ensuite l'enregistrement à AWS S3 en utilisant FlySystemen s'appuyant sur le AWS SDK pour la connectivité.

Transcrire

L'étape finale consiste à créer l'intergiciel basé sur les routes pour demander la transcription par l'application Amazon Transcribe par le service Amazon Transcribe. Voici comment procéder :

$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);
});

Note : Le SDK AWS obtient le login et la clé de l'environnement.

Dans cet intergiciel, nous analysons la charge utile JSON dans la demande afin d'obtenir les informations suivantes conversation_uuid.

Ensuite, un client Amazon Transcribe est utilisé pour créer un travail de transcription en utilisant le fichier MP3 stocké sur S3.

Conclusion

À l'aide de cet exemple, nous avons pu recevoir un appel vers un numéro Numbers, inviter l'appelant à laisser un message, récupérer le message au format MP3 et le stocker sur AWS S3, puis demander à Amazon Transcribe de convertir la parole en texte.

À partir de là, le texte peut être récupéré à partir d'AWS Transcribe via la console AWS, ou nous pourrions peut-être créer une sorte de tâche programmée pour vérifier périodiquement avant de télécharger pour d'autres utilisations.

Pour un exemple de code complet, voir https://github.com/nexmo-community/voice-aws-speechtotext-php.

Partager:

https://a.storyblok.com/f/270183/384x384/b3c7ffaf85/adamculp.png
Adam CulpAnciens de Vonage

Adam est un développeur et un consultant qui aime l'ultra-course, les blogs, et qui aide les autres à apprivoiser la technologie pour accomplir des choses étonnantes avec un désir insatiable de mentorat et d'aide.