KI: Bücher einfach vorlesen lassen

Was mich an der Informatik ja reizt ist, dass man mit seinem Notebook vor der größten LEGO-Kiste der Welt steht und nur die Zeit einen vor der Umsetzung von großen Ideen trennt. Es gibt eigentlich nichts, was man sich nicht vornehmen kann. Vor allem durch die Verfügbarkeit von den zahlreichen Cloud-Diensten hat man sogar privat Zugriff auf gigantische Hardware-Systeme, die früher nur mit einem eigenen Rechenzentrum zu bewerkstelligen waren.
Wenn ich Lust habe, kann ich mir einen PC mit 16 CPU-Kernen und 4 Grafikkarten in der Cloud starten, drauf rumspielen und wieder runterfahren (letzteres ist für den Geldbeutel entscheidend). So auch auf KI, Künstliche Intelligenz.

In diesem Beitrag zeige ich, wie ich mit Hilfe von Texterkennung und Sprachsynthese eine Vorlese-App entwickle.

Das Ergebnis des Projekts

Für meine kurzweiligen Basteleien sind aber vor allem APIs besonders spannend, also Schnittstellen (Bausteine), die fertige Lösungen für die eigenen Projekte zur Verfügung stellen. Dieses mal bin ich an zwei von ihnen hängen geblieben:

  • Google Gloud Vision
    Eine fertige Bilderkennung. Einfach ein Bild hinschicken und man bekommt eine umfangreiche Auswertung zurück. 
  • Google Cloud Text-To-Speech
    Einfach Text hinschicken und man bekommt ein Audio zurück. Mit inzwischen erstaunlich guter Qualität.

Meine fixe Idee: Warum nicht Google dazu bringen, mir meine Bücher vorzulesen? Besonders spannend, wenn man mal keine Hände und Augen zum Lesen frei hat. So wie beim Autofahren oder beim morgendlichen Sport.

Das Ergebnis sollte eine kleine App werden, bei der man fix die Buchseiten hintereinander abfotografieren und dann geschlossen anhören kann. 
Damit das Ganze auf iPhone und Android klappt, hab ich mich für eine Webapp auf Basis von Angular entschieden.

Die Steps waren also klar:
– Gucken, wie ich den Text aus den Bildern bekomme
– Text-To-Speech API ausprobieren
– Das Ganze in einer “App” zusammenzimmern

Gucken, wie ich den Text aus den Bildern bekomme

Anfangs dachte ich, ich müsste mich noch groß mit der Google-Client-Bibliothek rumschlagen. Aber die beiden APIs, können beide über einen generierten API-Token und über einen sehr einfachen API-Request verwendet werden.

$params= array(
 "requests"=> array(
 array(
 "features"=> array(array("type"=> "DOCUMENT_TEXT_DETECTION")),
 "image"=> array(
 "content" => base64_encode(file_get_contents($_FILES['photo']['tmp_name']))
 )
 )
 )
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://vision.googleapis.com/v1/images:annotate?key=$apiKey");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/plain'));
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec ($ch);
curl_close ($ch);

Der Trick ist vor allem DOCUMENT_TEXT_DETECTION, der dafür sorgt, dass Google selbstständig erkannte Textblöcke zu einem Paragraphen zusammenfasst. Ansonsten bekommt man einen Haufen von Textblöcken, die nicht einmal unbedingt in der richtigen Reihenfolge sind.
Die Texterkennung war damit erstaunlich schnell erledigt.

Text-To-Speech Api ausprobieren

Die Wiedergabe des Textes ist fast genauso einfach:

$output=array(
    "audioConfig"=> array(
        "audioEncoding"=> "MP3",
        "pitch"=> "0.00",
        "speakingRate"=> "1.00"
    ),
    "input"=> array(
        "ssml"=> $content
    ),
    "voice"=> array(
        "languageCode"=> "de-DE",
        "name"=> "de-DE-Wavenet-B"
    )
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"https://texttospeech.googleapis.com/v1beta1/text:synthesize?key=$apiKey");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER,     array('Content-Type: text/plain'));
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($output));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec ($ch);
curl_close ($ch);

Das Einzige, was noch getan werden muss, ist die Rückgabe aus seinem Base64-Encoding zu befreien und in eine MP3-Datei zu überführen.

$obj=json_decode($server_output);
file_put_contents($filename, base64_decode($obj->audioContent));

Das war es eigentlich schon. 

Das Ganze in einer „App“ zusammenzimmern

Um fix zu einem Ergebnis zu kommen, habe ich Angular 6 eingesetzt. Damit lässt sich mit nur einem Befehl eine komplette App-Architektur samt Routing erstellen.

ng new readit --is --prefix=ts --routing

Kurz danach hab ich gemerkt, dass ich für meine kleine Playlist gar kein Routing brauche, aber naja.

Damit die App auch ein bisschen nach was aussieht, habe ich PrimeNG eingebunden. Die Bibliothek bietet viele nützliche Widgets und war schon in einigen Projekten ein guter Begleiter.

Die App besteht eigentlich nur aus der Playlist-Komponente und einem API-Service, der die Endpunkte am Server mit Daten versorgt. Aktuell gibt es zwei Endpunkte.

/upload.php — Nimmt stumpf die Bilder an und wandelt sie in Text um.
/tts.php — Generiert eine MP3-Datei und gibt die URL zurück.

Für das Hosting habe ich am Ende die Google App Engine noch eingebunden. Damit ist mein kleines Bastelprojekt eine echte Cloud-Anwendung ☺️.

Probiert es einfach mal aus unter: https://read.tobias-sell.com

Spannend? Lass uns Gedanken austauschen!