Een toepassing die echt een natuurlijke taal begrijpt, hebben sci-fi-enthousiasten, programmeurs en AI-onderzoekers al decennia gedroomd. Dankzij de grote vooruitgang op het gebied van technologie voor het leren van machines is deze droom vandaag de dag dichterbij dan ooit om werkelijkheid te worden. Bovendien hebben cloudgebaseerde services zoals Google Cloud Machine Learning deze technologieën vrij toegankelijk gemaakt voor iedereen.
In deze zelfstudie leert u hoe u twee krachtige op natuurlijke taal gebaseerde API's kunt gebruiken die worden aangeboden door het Google Cloud Machine Learning-platform: Cloud Speech API en Cloud Natural Language API. Door ze samen te gebruiken, kunt u apps maken die spraak kunnen verwerken in een groot aantal veel gesproken talen.
Om mee te gaan, heb je nodig:
Een toepassing die spraak kan verwerken, moet de volgende mogelijkheden hebben:
Met de API's voor cloud-spraak en cloud-natuurlijke taal kunt u de bovenstaande functies binnen enkele minuten aan uw Android-app toevoegen.
De Cloud Speech-API dient als een geavanceerde spraakherkenner waarmee spraak in meer dan 80 talen nauwkeurig kan worden getranscribeerd. Het kan ook robuuste regionale accenten en lawaaierige omstandigheden verwerken.
Een soortgelijke opmerking is dat de Cloud Natural Language API een taalverwerkingssysteem is dat, met nauwkeurigheid op het niveau van de mens, de rollen kan bepalen die woorden spelen in zinnen die eraan worden gegeven. Het ondersteunt momenteel tien talen en biedt ook analyse van entiteiten en sentimenten.
Voordat u de API's Spraak en Natuurlijke taal gebruikt, moet u ze inschakelen in de Google Cloud-console. Dus log in op de console en navigeer naar API Manager> Bibliotheek.
Om de Speech API in te schakelen, klikt u op de Spraak-API link in de Google Cloud Machine Learning sectie. Op de volgende pagina opent u de in staat stellen knop.
Druk op de terugtoets van uw browser om terug te gaan naar de vorige pagina.
Schakel deze keer de Natural Language API in door op te klikken Natuurlijke taal-API link en druk op de in staat stellen knop op de volgende pagina.
U heeft een API-sleutel nodig tijdens de interactie met de API's. Als u er nog geen heeft, opent u de Geloofsbrieven tab, druk op de Aanmeldingsgegevens maken knop en kies API sleutel.
U ziet nu een pop-up met uw API-sleutel. Noteer het zodat je het later kunt gebruiken.
Beide API's zijn gebaseerd op JSON en hebben REST-eindpunten waarmee u rechtstreeks kunt communiceren via een netwerkbibliotheek. U kunt echter veel tijd besparen - en ook meer leesbare code schrijven - door de Google API Client-bibliotheken te gebruiken die voor hen beschikbaar zijn. Open dus de build.gradle bestand van uw project app
module en voeg het volgende toe compileren
afhankelijkheden ervan:
compileer 'com.google.api-client: google-api-client-android: 1.22.0' compileer 'com.google.apis: google-api-services-speech: v1beta1-rev336-1.22.0' compile 'com. google.apis: google-api-services-language: v1beta2-rev6-1.22.0 'compile' com.google.code.findbugs: jsr305: 2.0.1 '
Bovendien zullen we een paar bestands-I / O-bewerkingen uitvoeren in deze zelfstudie. Voeg a toe om ze te vereenvoudigen compileren
afhankelijkheid van de Commons IO-bibliotheek.
compileer 'commons-io: commons-io: 2.5'
Vergeet ten slotte niet te vragen om de INTERNET
toestemming in de AndroidManifest.xml het dossier. Zonder dit kan uw app geen verbinding maken met de servers van Google.
Het spreekt voor zich dat de Cloud Speech API audiodata verwacht als een van zijn ingangen. Daarom zullen we nu een Android-app maken die audiobestanden kan transcriberen.
Om het simpel te houden, zullen we alleen FLAC-bestanden transcriberen, bestanden die het coderingsformaat Free Lossless Audio Codec gebruiken. Mogelijk hebt u dergelijke bestanden al op uw apparaat. Als u dat niet doet, raad ik u aan een paar van Wikimedia Commons te downloaden.
De lay-out van onze app heeft een Knop
widget gebruikers kunnen op drukken om een bestandskiezer te tonen, een interface waar ze door kunnen bladeren en audiobestanden kunnen selecteren die beschikbaar zijn op hun apparaten.
De lay-out heeft ook een Tekstweergave
widget om het transcript van het geselecteerde audiobestand weer te geven. Voeg daarom de volgende code toe aan het lay-out XML-bestand van uw activiteit:
De interface van de bestandskiezer moet worden weergegeven wanneer de gebruiker op de knop drukt die we in de vorige stap hebben gemaakt, dus associeer een OnClickListener
object ermee. Voordat u dit doet, moet u de knop initialiseren met behulp van de findViewById ()
methode.
Knop browseButton = (Button) findViewById (R.id.browse_button); browseButton.setOnClickListener (nieuwe View.OnClickListener () @Override public void onClick (View view) // Meer code hier);
Met Android's Storage Access Framework, dat beschikbaar is op apparaten met API-niveau 19 of hoger, kost het maken van een bestandskiezer weinig moeite. Het enige wat u hoeft te doen is een intentie creëren voor de ACTION_GET_CONTENT
actie en geef deze door aan de startActivityForResult ()
methode. Optioneel kunt u de bestandskiezer beperken om alleen FLAC-bestanden weer te geven door het juiste MIME-type door te geven aan de settype ()
methode van de voornemen
voorwerp.
Intent filePicker = new Intent (Intent.ACTION_GET_CONTENT); filePicker.setType ( "audio / flac"); startActivityForResult (filePicker, 1);
De uitvoer van de bestandskiezer zal een andere zijn voornemen
object met de URI van het bestand dat de gebruiker heeft geselecteerd. Om toegang te krijgen, moet u de onActivityResult ()
methode van uw Activiteit
klasse.
@Override beschermde leegte onActivityResult (int requestCode, int resultCode, Intent-gegevens) super.onActivityResult (requestCode, resultCode, data); if (resultCode == RESULT_OK) final Uri soundUri = data.getData (); // Meer code hier
De Cloud Speech API verwacht dat de audiogegevens de vorm hebben van een Base64-reeks. Om een dergelijke reeks te genereren, kunt u de inhoud van het bestand lezen dat de gebruiker heeft geselecteerd in a byte
array en geef deze door aan de encodeBase64String ()
hulpprogramma-methode aangeboden door de Google API Client-bibliotheek.
U hebt momenteel echter alleen de URI van het geselecteerde bestand en niet het absolute pad. Dat betekent dat u eerst de URI moet kunnen oplossen om het bestand te kunnen lezen. U kunt dit doen door het door te geven aan de openInputStream ()
methode van de inhoudsoplosser van uw activiteit. Zodra u toegang hebt tot de invoerstroom van het bestand, kunt u het gewoon doorgeven aan de toByteArray ()
methode van de IOUtils
klasse om het in een array van bytes om te zetten. De volgende code laat zien hoe:
AsyncTask.execute (nieuw Runnable () @Override public void run () InputStream stream = getContentResolver () .openInputStream (soundUri); byte [] audioData = IOUtils.toByteArray (stream); stream.close (); String base64EncodedData = Base64.encodeBase64String (audioData); // Meer code hier
Zoals je kunt zien in de bovenstaande code, gebruiken we een nieuwe thread om alle I / O-bewerkingen uit te voeren. Dit is belangrijk om ervoor te zorgen dat de gebruikersinterface van de app niet vastloopt.
Naar mijn mening is het een goed idee om het geluidsbestand af te spelen dat wordt getranscribeerd terwijl het wordt getranscribeerd. Het kost niet veel moeite en het verbetert de gebruikerservaring.
U kunt de Mediaspeler
klasse om het geluidsbestand af te spelen. Zodra u het naar de URI van het bestand verwijst met behulp van zijn setDataSource ()
methode, je moet het bellen bereiden()
methode om de speler synchroon voor te bereiden. Wanneer de speler klaar is, kunt u bellen met de begin()
methode om het bestand af te spelen.
Bovendien moet u eraan denken om de bronnen van de speler vrij te geven nadat het afspelen van het bestand voltooid is. Om dit te doen, wijst u een OnCompletionListener
er bezwaar tegen hebben en het zijn vrijlating()
methode. De volgende code laat zien hoe:
MediaPlayer-speler = nieuwe MediaPlayer (); player.setDataSource (MainActivity.this, soundUri); player.prepare (); player.start (); // Laat de speler player.setOnCompletionListener (nieuwe MediaPlayer.OnCompletionListener () @Override public unfid onCompletion (MediaPlayer mediaPlayer) mediaPlayer.release (););
Op dit punt kunnen we de Base64-gecodeerde audiogegevens naar de Cloud Speech API verzenden om deze te transcriberen. Maar eerst stel ik voor dat u de API-sleutel die u eerder hebt gegenereerd, opslaat als een ledvariabele van uw Activiteit
klasse.
private finale String CLOUD_API_KEY = "ABCDEF1234567890";
Om te kunnen communiceren met de Cloud Speech API, moet u een Toespraak
object met behulp van een Speech.Builder
aanleg. Als argumenten verwacht de constructor een HTTP-transport en een JSON-fabriek. Bovendien moet u een koppeling maken om ervoor te zorgen dat de API-sleutel wordt opgenomen in elk HTTP-verzoek aan de API SpeechRequestInitializer
object met de bouwer en geef de sleutel door.
De volgende code maakt een Toespraak
object met behulp van de AndroidJsonFactory
klasse als de JSON-fabriek en de NetHttpTransport
klasse als het HTTP-transport:
Speech speechService = nieuwe Speech.Builder (AndroidHttp.newCompatibleTransport (), nieuwe AndroidJsonFactory (), null) .setSpeechRequestInitializer (nieuwe SpeechRequestInitializer (CLOUD_API_KEY)) .build ();
De Cloud Speech API moet worden verteld in welke taal het audiobestand zich bevindt. U kunt dit doen door een RecognitionConfig
object en noem het setLanguageCode ()
methode. Zo configureer je het om alleen Amerikaans Engels te transcriberen:
RecognitionConfig recognitionConfig = new RecognitionConfig (); recognitionConfig.setLanguageCode ( "en-US");
Bovendien moet de Base64-gecodeerde string worden ingepakt in een RecognitionAudio
object voordat het door de API kan worden gebruikt.
RecognitionAudio recognitionAudio = new RecognitionAudio (); recognitionAudio.setContent (base64EncodedData);
Vervolgens gebruikt u de RecognitionConfig
en RecognitionAudio
objecten, moet je een maken SyncRecognizeRequest
voorwerp. Zoals de naam al doet vermoeden, kunt u hiermee een HTTP-verzoek maken om audiodata synchroon te transcriberen. Nadat het object is gemaakt, kunt u het als argument doorgeven aan de syncrecognize ()
methode en bel de resulterende Speech.SpeechOperations.Syncrecognize
voorwerpen execute ()
methode om het HTTP-verzoek daadwerkelijk uit te voeren.
De retourwaarde van de execute ()
methode is een SyncRecognizeResponse
object, dat verschillende alternatieve transcripten kan bevatten. Voorlopig gebruiken we alleen het eerste alternatief.
// Aanvraag creëren SyncRecognizeRequest-aanvraag = nieuwe SyncRecognizeRequest (); request.setConfig (recognitionConfig); request.setAudio (recognitionAudio); // Reactie genereren SyncRecognizeResponse response = speechService.speech () .syncrecognize (request) .execute (); // Transcript uitpakken SpeechRecognition Resultaatresultaat = response.getResults (). Get (0); final String transcript = result.getAlternatives (). get (0) .getTranscript ();
Als laatste, om het transcript naar de gebruiker weer te geven, kunt u het doorgeven aan de Tekstweergave
widget. Natuurlijk, omdat wijzigingen in de gebruikersinterface altijd moeten gebeuren in de UI-thread, moet u dit doen nadat u uw activiteiten heeft gebeld runOnUiThread ()
methode.
runOnUiThread (nieuw Runnable () @Override public void run () TextView speechToTextResult = (TextView) findViewById (R.id.speech_to_text_result); speechToTextResult.setText (transcript););
U kunt nu uw app uitvoeren, een FLAC-bestand selecteren dat spraak in Amerikaans-Engels bevat en de Cloud Speech-API een transcript voor het zien genereren.
Het is de moeite waard te vermelden dat de Cloud Speech API momenteel alleen audiobestanden met één kanaal kan verwerken. Als u een bestand met meerdere kanalen ernaar verzendt, krijgt u een foutantwoord.
Nu we een transcript hebben, kunnen we het doorgeven aan de Cloud Natural Language API om het te analyseren. Om deze tutorial kort te houden, zullen we alleen entiteits- en sentimentanalyse uitvoeren op het transcript. Met andere woorden, we gaan alle entiteiten bepalen die in het transcript worden genoemd, zoals mensen, plaatsen en beroepen, en ook vertellen of het algemene sentiment negatief, neutraal of positief is.
Om de gebruiker toe te staan de analyse te starten, moet onze lay-out een andere bevatten Knop
widget. Voeg daarom de volgende code toe aan het XML-bestand met de lay-out van uw activiteit:
De Cloud Natural Language REST API biedt een geroemde gemaksoptie annotateText waarmee u zowel sentiment- als entiteitsanalyse op een document kunt uitvoeren met slechts één HTTP-verzoek. We zullen het gebruiken om ons transcript te analyseren.
Omdat de analyse moet beginnen wanneer de gebruiker op de knop drukt die we in de vorige stap hebben gemaakt, voegt u een toe OnClickListener
ernaar toe.
Button analysisButton = (Button) findViewById (R.id.analyze_button); analyzeButton.setOnClickListener (nieuwe View.OnClickListener () @Override public void onClick (View view) // Meer code hier);
Als u wilt communiceren met de API met behulp van de Google API Client-bibliotheek, moet u een CloudNaturalLanguage
object met behulp van de CloudNaturalLanguage.Builder
klasse. De constructeur verwacht ook een HTTP-transport en een JSON-fabriek.
Verder door het toewijzen van een CloudNaturalLanguageRequestInitializer
In dit geval kunt u het dwingen om uw API-sleutel in al zijn aanvragen op te nemen.
final CloudNaturalLanguage naturalLanguageService = new CloudNaturalLanguage.Builder (AndroidHttp.newCompatibleTransport (), new AndroidJsonFactory (), null) .setCloudNaturalLanguageRequestInitializer (new CloudNaturalLanguageRequestInitializer (CLOUD_API_KEY)) .build ();
Alle tekst die u met de API wilt analyseren, moet in een. Worden geplaatst Document
voorwerp. De Document
object moet ook configuratie-informatie bevatten, zoals de taal van de tekst en of deze is opgemaakt als platte tekst of HTML. Voeg daarom de volgende code toe:
String transcript = ((TextView) findViewById (R.id.speech_to_text_result)) .getText (). ToString (); Document document = nieuw document (); document.setType ( "PLAIN_TEXT"); document.setLanguage ( "en-US"); document.setContent (transcript);
Vervolgens moet u een maken Kenmerken
object met de functies die u wilt analyseren. De volgende code laat zien hoe u een maakt Kenmerken
object dat zegt dat u entiteiten wilt extraheren en alleen een sentimentanalyse wilt uitvoeren.
Functies kenmerken = nieuwe functies (); features.setExtractEntities (true); features.setExtractDocumentSentiment (true);
U kunt nu de Document
en Kenmerken
objecten om een te vormen AnnotateTextRequest
object, dat kan worden doorgegeven aan de annotateText ()
methode om een te genereren AnnotateTextResponse
voorwerp.
final AnnotateTextRequest request = new AnnotateTextRequest (); request.setDocument (document); request.setFeatures (kenmerken); AsyncTask.execute (nieuw Runnable () @Override public void run () AnnotateTextResponse response = naturalLanguageService.documents () .annotateText (request) .execute (); // Meer code hier
Merk op dat we het antwoord in een nieuwe thread genereren omdat netwerkbewerkingen niet zijn toegestaan in de UI-thread.
U kunt een lijst met entiteiten extraheren uit de AnnotateTextResponse
object door het te bellen getEntities ()
methode. Evenzo kunt u het algemene sentiment van het transcript extraheren door het getDocumentSentiment ()
methode. Om de werkelijke score van het sentiment te krijgen, moet u echter ook het getScore ()
methode, die a retourneert vlotter
.
Zoals je zou verwachten, betekent een sentimentscore gelijk aan nul: het sentiment is neutraal, een score groter dan nul betekent dat het sentiment positief is en een score kleiner dan nul betekent dat het sentiment negatief is.
Wat u doet met de lijst van entiteiten en de sentimentscore is natuurlijk aan u. Laten we ze nu allebei weergeven met een AlertDialog
aanleg.
laatste lijstentityList = response.getEntities (); laatste float-sentiment = response.getDocumentSentiment (). getScore (); runOnUiThread (nieuw Runnable () @Override openbare ongeldige run () String entities = ""; for (Entiteit entiteit: entityList) entities + = "\ n" + entity.getName (). toUpperCase (); Dialoogvenster AlertDialog = new AlertDialog.Builder (MainActivity.this) .setTitle ("Sentiment:" + sentiment) .setMessage ("Dit audiobestand spreekt over:" + entiteiten) .setNeutralButton ("Okay", null) .create (); dialoogvenster. laten zien(); );
Met de bovenstaande code wordt de sentimentscore weergegeven in de titel van het dialoogvenster en wordt de lijst met entiteiten weergegeven in de body.
Als u de app nu uitvoert, moet u de inhoud van audiobestanden kunnen analyseren en deze ook kunnen transcriberen.
U weet nu hoe u de API's Cloud Speech en Cloud Natural Language samen kunt gebruiken om een Android-app te maken die niet alleen een audiobestand kan transcriberen, maar ook een entiteits- en sentimentanalyse kan uitvoeren. In deze zelfstudie leer je ook hoe je kunt werken met het Storage Access Framework en Google Client API-bibliotheken van Android.
Google heeft regelmatig nieuwe en interessante functies toegevoegd, samen met ondersteuning voor meer talen, aan beide API's. Raadpleeg de officiële documentatie om op de hoogte te blijven.
En terwijl je hier bent, bekijk een aantal van onze andere berichten over cloudservices voor mobiele apps en machine learning!