{Acapela} – Ajoutez de la synthèse vocale dans vos applications Web / Mobile

Bonjour à tous,

 

Aujourd'hui je suis actuellement entrain de préparer un beau diaporama pour le "mariage" d'un ami.
Et forcément dans ce genre de situation, nous essayons tous de trouver des petits trucs sympas à faire.
Dans les choses que je dois préparer, j'ai un discours à lire (ou à faire lire ;) )
Bref j'ai creusé un peu et je me suis rendu compte que le "hack" que je vous avais écrit il y  a quelques années pour Voxygen n'était plus d'actualité :s

J'ai donc recherché une solution alternative qui ne propose pas une voix robotique à la sauce "Hello Google" .

C'est ainsi, que j'ai redécouvert un service plutôt mal référencé répondant au nom de : "Acapela"

Une plateforme payante

Forcément, le service n'est pas gratuit, mais il y a une période d'essai :

Compte d’évaluation gratuit

Enregistrez-vous pour accéder au compte d’évaluation gratuit. Vous bénéficierez de 30 jours d’essai et 100 messages par jour. Vous aurez accès pendant cette période à toutes les fonctions, langues et voix.

On dénotera néanmoins un bel effort de la part de cette entreprise pour les développeurs :

Niveau tarif je n'ai pas trouvé d'informations à ce sujet.
Si vous en avez, n’hésitez pas à partager en commentaire.

 

Reverse Engineering

Ce petit "chapitre" va vous détailler la manière dont fonctionne l'outil de démonstration d'Acapela.
Cet outil est bien entendu "gratuit" étant donné qu'il est mis à disposition de tout le monde sur la plateforme et sans limite de temps ;)
J'ai donc fait un peu de reverse engineering afin de l'exploiter en PHP.

La démonstration suivante se fait avec la console de votre navigateur (Touche F12 de votre clavier, onglet Network sur Google Chrome)

Lorsque vous avez rempli et validé votre formulaire sur Acapela :

Une première requête est réalisée par la plateforme :

https://www.acapela-group.com/www/static/website/demoOptionsDef_voicedemo.php?_=1542122540600

Cette requête va permettre de récupérer un certain nombre d'informations (login, app, url du service de génération des fichiers mp3 et ogg, token, ....)

 

Ces informations seront utilisées pour générer la prochaine requête, qui se présente sous cette forme-là :

https://h-ir-ssd-1.acapela-group.com/webservices/1-60-00/Streamer.mp3?cl_login=<login>&cl_app=<app>&session_start=<start>&session_time=<time>&session_key=<key>&req_voice=sharon22k&req_text=Hello World

L'url en rouge correspond ici à la valeur "mp3_service_url" récupérée dans la précédente requête.
Les données en vert sont à remplacer par les données récupérées dans la précédente requête.

En bleu il faut renseigner un texte à lire et un lecteur.

J'ai dressé ci-dessous une liste des lecteurs :

Arabic => 				["leila22k","mehdi22k","nizar22k","salma22k"]
Catalan => ["laia22k"]
Czech => ["eliska22k"]
Danish => ["mette22k","rasmus22k"]
Dutch (Belgium) => ["zoe22k","jeroen22k","jeroenhappy (emotive voice)22k","jeroensad (emotive voice)22k","sofie22k"]
Dutch (Netherlands) => ["jasmijn22k","daan22k","femke22k","max22k"]
English (AU) => ["tyler22k","lisa22k"]
English (India) => ["deepa22k"]
English (Scottish) => ["rhona22k"]
English (UK) => ["rachel22k","graham22k","lucy22k","nizareng22k","peter22k","peterhappy (emotive voice)22k","petersad (emotive voice)22k","queenelizabeth (her majesty)22k"]
English (USA) => ["sharon22k","karen22k","kenny (artificial child voice)22k","laura22k","micah22k","nelly (artificial child voice)22k","rod22k","ryan22k","saul22k","tracy22k","will22k","willbadguy (emotive voice)22k","willfromafar (emotive voice)22k","willhappy (emotive voice)22k","willlittlecreature (emotive voice)22k","willoldman (emotive voice)22k","willsad (emotive voice)22k","willupclose (emotive voice)22k"]
Faroese => ["hanna22k","hanus22k"]
Finnish => ["sanna22k"]
French (Belgium) => ["manon-be22k","alice-be22k","anais-be22k","antoine-be22k","bruno-be22k","claire-be22k","julie-be22k","margaux-be22k"]
French (Canada) => ["louise22k"]
French (France) => ["manon22k","alice22k","anais22k","antoine22k","antoinefromafar (emotive voice)voice)22k","antoinehappy (emotive voice)22k","antoinesad (emotive voice)22k","antoineupclose (emotive voice)22k","bruno22k","claire22k","julie22k","margaux22k","margauxhappy (emotive voice)22k","margauxsad (emotive voice)22k"]
German => ["claudia22k","andreas22k","claudiasmile (emotive voice)22k","julia22k","klaus22k","sarah22k"]
Greek => ["dimitris22k","dimitrishappy (emotive voice)22k","dimitrissad (emotive voice)22k"]
Italian => ["fabiana22k","chiara22k","vittorio22k"]
Japanese => ["sakura22k"]
Korean => ["minji22k"]
Mandarin => ["lulu22k"]
Norwegian => ["bente22k","kari22k","olav22k"]
Polish => ["ania22k"]
Portuguese (Brazil) => ["marcia22k"]
Portuguese (Portugal) => ["celia22k"]
Russian => ["alyona22k"]
Sami (North) => ["biera22k","elle22k"]
Spanish (Spain) => ["ines22k","maria22k"]
Spanish (US) => ["rodrigo22k","rosa22k"]
Swedish => ["elin22k","emil22k","emma22k","erik22k"]
Swedish (Finland) => ["samuel22k"]
Swedish (Gothenburg) => ["kal22k"]
Swedish (Scanian) => ["mia22k"]
Turkish => ["ipek22k"]

J'ai obtenu cette liste dans le fichier demo.js

 

L'API PHP

Parfois je vous fais des scripts en python, parfois en JS ... aujourd'hui ça sera du PHP !
Ça permet de varier un peu les goûts et les couleurs ;)

<?php
/*
*
* Acapela Tricks
* (c) Dyrk.org
* 2018-2019
*
*/

class Accapela{
public function __construct(){
$this->getSession();
}
private function getSession(){
$contents = file_get_contents("https://www.acapela-group.com/www/static/website/demoOptionsDef_voicedemo.php?_=".date('U'));
$session = json_decode(str_replace(array('var vaasOptions = ',';'), array('',''), $contents) ,true);
$this->Mp3Url = $session['mp3_service_url'];
$this->OggUrl = $session['ogg_service_url'];
$session = $session['session'];
$this->session = Array(
'cl_login' => 'AcapelaGroup',
'cl_app' => 'AcapelaGroup_WebDemo_HTML',
'session_start' => $session['start'],
'session_time' => $session['time'],
'session_key' => $session['key']
);

}
public function readText($reader, $text){
$url = $this->Mp3Url."?";
foreach ($this->session as $k => $v)
$url .= "&$k=$v";
$url .= "&req_voice=$reader&req_text=".$text;
print $url;
}
};

?>

Vous pouvez utiliser cette API de la manière suivante :

<?php
$test = new Accapela;
$test->readText('bruno22k','Hello World');
?>

La méthode 'readText' vous renverra l'url du MP3 généré par la plateforme Acapela.

 

Un hack temporaire

Une fois n'est pas coutume, je tiens à vous rappeler qu'il s'agit d'un produit qui est vendu.
Donc des gens qui ont travaillé pour le fabriquer.
Tout travail mérite salaire.
Il n'est pas dit que demain, Acapela supprimera son service de démo, ou appliquera des mesures de sécurité qui empêcheront l'api que je vous ai fourni, de fonctionner.

 

 Conclusion

Je vous souhaite à tous de bonnes fêtes de fin d'année et j'invite ceux qui le peuvent à acheter le produit ;)
(Je ne suis pas sponsorisé pour dire ça, mais je pense qu'un coup de pub pour un bon service ça fait toujours plaisir)
Je devrais mettre une petite cagnotte en ligne bientôt pour ceux qui souhaitent faire un don à Dyrk (toujours utile pour acheter du matos, payer le serveur, le nom de domaine, etc ...)

 

 

 

Mise à jour

=========

J'ai constaté suite à l'un de vos commentaires, que la plateforme Acapela avait mis à jour son mécanisme de génération des fichiers mp3.
Je vous propose donc une nouvelle adaptation de mon code PHP

<?php


class Accapela{
public function __construct(){
$this->getSession();
$this->mp3Url = 'https://h-ir-ssd-1.acapela-group.com/webservices/1-60-00/UrlMaker.json';
}
private function getSession(){
$contents = file_get_contents("https://www.acapela-group.com/www/static/website/demoOptionsDef_voicedemo.php?_=".date('U'));
$session = json_decode(str_replace(array('var vaasOptions = ',';'), array('',''), $contents) ,true);
$session = $session['session'];
$this->session = Array(
'cl_login' => 'AcapelaGroup',
'cl_app' => 'AcapelaGroup_WebDemo_HTML',
'session_start' => $session['start'],
'session_time' => $session['time'],
'session_key' => $session['key']
);

}

private function getMp3(){
$fields_string = "";
foreach($this->session as $key=>$value)
$fields_string .= $key.'='.$value.'&';
rtrim($fields_string, '&');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL , $this->mp3Url);
curl_setopt($ch, CURLOPT_POST , count($this->session));
curl_setopt($ch, CURLOPT_POSTFIELDS , $fields_string);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER , FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER , 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION , true);
$result = curl_exec($ch);
$datas = curl_getinfo($ch);
curl_close($ch);
return json_decode($result,true)['snd_url'];
}

public function readText($reader, $text){
$url = $this->mp3Url."?";
$this->session['req_voice'] = $reader;
$this->session['req_text'] = $text;
echo $this->getMp3();
}
};

?>

3 comments

  • Salut à tous.

    Super article encore.

    J’avais déjà fait pas mal de recherche sur les synthèses vocales « on line » il est vrai qu’Accapela fonctionne vraiment bien avec un choix hallucinant de langue et d’émotion.

    À l’époque je récupérais le fichier mp3 dans le cache d’internet exploreur…

    Moi j’utilise de temps en temps ce site « https://text-to-speech-demo.ng.bluemix.net/ » qui est entièrement gratuit mais bien moins fourni avec un rendu assez bon malgré tous.

    Pour Accapela je n’arrive pas à créer de compte de démo… sniff! pour faire quelque essaie donc le script PHP ne fonctionne pas ou alors je n’arrive pas à l’utiliser Help help help :)…..

    Merci pour ton travail!!!!!!!!!!

    @+

    • Hello Irus1980,

      Bonne année à toi !
      Tout d’abord merci !
      En effet j’ai constaté grâce à ton commentaire que la plateforme Accapela avait en effet, réalisé une mise à jour de sa manière de générer des MP3.
      J’ai donc ajusté mon code, que tu pourras retrouver à la fin de l’article ;)

      • Salut à toi.

        Oui Meilleure vœux pour 2019 à tous…… :)

        Pour que le script fonctionne il faut avoir un compte d’évaluation ? mais impossible de le crée je pense qu’il on bloqué les inscription.

        Bonne journée @+

Laisser une réponse

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site est protégé par reCAPTCHA et le GooglePolitique de confidentialité etConditions d'utilisation appliquer.