Använda taligenkännings API i IOS 10

Vad du ska skapa

Introduktion

Siri har varit en kärnfunktion iOS sedan den introducerades tillbaka 2011. Nu levererar iOS 10 nya funktioner för att tillåta utvecklare att interagera med Siri. I synnerhet finns nu två nya ramar: Tal och SiriKit. 

Idag ska vi ta en titt på talramen, vilket gör att vi enkelt kan översätta ljud till text. Du lär dig att bygga en verklig app som använder taligenkännings API för att kontrollera status för ett flyg.

Om du vill lära dig mer om SiriKit täckte jag det i min Skapa SiriKit Extensions i IOS 10 handledning. För mer om de andra nya funktionerna för utvecklare i IOS 10, kolla Markus Mühlberger kurs, här på Envato Tuts+.

Användande

Taligenkänning är processen att översätta live eller förinspelat ljud till transkriberad text. Sedan Siri introducerades i iOS 5 har det funnits en mikrofonknapp i systemtangentbordet som gör att användarna enkelt kan diktera. Den här funktionen kan användas med någon UIKit-textinmatning, och det kräver inte att du skriver tilläggskoden utöver vad du skulle skriva för att stödja en vanlig textinmatning. Det är verkligen snabbt och enkelt att använda, men det kommer med några begränsningar:

  • Tangentbordet är alltid närvarande när dikteras.
  • Språket kan inte anpassas av appen själv.
  • Appen kan inte meddelas när diktering startar och avslutas.

För att tillåta utvecklare att bygga mer anpassningsbara och kraftfulla applikationer med samma dikteringsteknik som Siri, skapade Apple talramen. Det tillåter varje enhet som kör iOS 10 för att översätta ljud till text på över 50 språk och dialekter.

Detta nya API är mycket kraftfullare eftersom det inte bara ger en enkel transkriptionstjänst, men det ger också alternativa tolkningar av vad användaren kanske har sagt. Du kan styra när du vill stoppa en diktering, du kan visa resultat som din användare talar och taligenkänningsmotorn anpassar sig automatiskt till användarinställningarna (språk, ordförråd, namn etc.). 

En intressant funktion är stöd för transkribering av förinspelat ljud. Om du bygger en snabbmeddelandeprogram kan du till exempel använda den här funktionen för att skriva om texten till nya ljudmeddelanden.

Inrätta

Först och främst måste du be användaren om tillstånd att överföra sin röst till Apple för analys. 

Beroende på enheten och språket som ska erkännas kan iOS självständigt bestämma att transkribera ljudet på enheten själv eller om det inte finns lokal taligenkänning på enheten, kommer iOS att använda Apples servrar för att göra jobbet. 

Det är därför som en aktiv internetanslutning vanligtvis krävs för taligenkänning. Jag ska visa dig hur du ska kontrollera tillgängligheten av tjänsten snart.

Det finns tre steg att använda taligenkänning:

  • Förklara: berätta för användaren varför du vill komma åt sin röst.
  • Auktorisera: Begär uttryckligen behörighet att få tillgång till sin röst.
  • Förfrågan: Ladda ett förinspelat ljud från skivan med SFSpeechURLRecognitionRequest, eller strömma live ljud med SFSpeechAudioBufferRecognitionRequest och bearbeta transkriptionen.

Om du vill veta mer om talramen, titta på WWDC 2016 Session 509. Du kan också läsa den officiella dokumentationen.

Exempel

Jag ska nu visa dig hur man bygger en verklig app som utnyttjar taligenkännings API. Vi ska bygga en liten flygspårningsapp där användaren helt enkelt kan säga ett flygnummer och appen visar aktuell status för flygningen. Ja, vi ska bygga en liten assistent som Siri för att kontrollera statusen för ett flyg!

I handledningens GitHub repo har jag lagt fram ett skelettprojekt som innehåller ett grundläggande användargränssnitt som hjälper oss till den här handledningen. Hämta och öppna projektet i Xcode 8.2 eller senare. Med en befintlig användargränssnitt kommer vi att fokusera på taligenkännings API.

Ta en titt på klasserna i projektet. UIViewController + Style.swift innehåller det mesta av koden som är ansvarig för uppdateringen av användargränssnittet. Exempeldatakällan för de flygningar som visas i tabellen förklaras i FlightsDataSource.swift.

Om du kör projektet ska det se ut som följande.

När användaren trycker på mikrofonknappen vill vi börja taligenkänningen för att transkribera flygnummeret. Så om användaren säger "LX40", skulle vi vilja visa informationen om grinden och nuvarande status för flygningen. För att göra detta kommer vi att ringa en funktion för att automatiskt se upp flygningen i en datakälla och visa status för flygningen. 

Vi kommer först att utforska hur man transkriberar från förinspelat ljud. Senare lär vi oss att implementera det mer intressanta live taligenkännetecknet.

Låt oss börja med att starta projektet. Öppna Info.plist fil och lägg till en ny rad med förklaringen som kommer att visas till användaren när du frågade om tillstånd att få åtkomst till sin röst. Den nyligen tillagda raden är markerad i blått i följande bild.

När detta är klart, öppna ViewController.swift. Tänk inte på koden som redan finns i den här klassen. Det tar bara hand om uppdatering av användargränssnittet för oss.

Det första steget med vilken ny ram du vill använda är att importera den högst upp i filen.

importera tal

För att visa behörighetsdialogrutan till användaren, lägg till den här koden i viewDidLoad (animerad :) metod:

byt SFSpeechRecognizer.authorizationStatus () case .notDetermined: askSpeechPermission () fall .authorized: self.status = .ready fall .denied, .restricted: self.status = .unavailable

De status variabel tar hand om att ändra användargränssnittet för att varna användaren att taligenkänning inte är tillgängligt om något går fel. Vi kommer att tilldela en ny status till samma variabel varje gång vi vill ändra användargränssnittet.

Om appen inte har frågat användaren för tillstånd än, kommer auktoriseringsstatusen att vara inte bestämd, och vi kallar askSpeechPermission metod att fråga det enligt definitionen i nästa steg.

Du borde Följer alltid graciöst om en specifik funktion inte är tillgänglig. Det är också mycket viktigt att alltid kommunicera med användaren när du spelar in sin röst. Försök aldrig känna igen sin röst utan att först uppdatera användargränssnittet och göra din användare medveten om det.

Här är implementeringen av funktionen för att fråga användaren om tillstånd.

func askSpeechPermission () SFSpeechRecognizer.requestAuthorization status i OperationQueue.main.addOperation switch status case .authorized: self.status = .ready default: self.status = .unavailable

Vi åberopar requestAuthorization Metod för att visa talesökningsskyddspolicyn som vi lagt till i Info.plist. Vi byter sedan till huvudgängan om stängningen anropades på en annan tråd - vi vill bara uppdatera användargränssnittet från huvudgängan. Vi tilldelar det nya status för att uppdatera mikrofonknappen för att signalera användaren om tillgängligheten (eller inte) för taligenkänning.

Förinspelad ljudigenkänning

Innan du skriver koden för att känna igen förinspelat ljud, måste vi hitta URL-adressen för ljudfilen. Kontrollera att du har en fil med namnet i projektnavigatorn LX40.m4a. Jag spelade in den här filen själv med Voice Memos-appen på min iPhone genom att säga "LX40". Vi kan enkelt kontrollera om vi får en korrekt transkription av ljudet.

Spara ljudfilens URL i en egenskap:

var preRecordedAudioURL: URL = return Bundle.main.url (forResource: "LX40", medExtension: "m4a")!  ()

Det är dags att äntligen se kraften och enkelheten i talramen. Detta är koden som gör all taligenkänning för oss:

func recognizeFile (url: URL) guard let recognizer = SFSpeechRecognizer (), recognizer.isAvailable else return låt request = SFSpeechURLRecognitionRequest (url: url) recognizer.recognitionTask (med: förfrågan) resultat, fel i vakt låt recognizer = SFSpeechRecognizer (), recognizer.isAvailable else return self.status = .unavailable om låt resultat = resultat self.flightTextView.text = result.bestTranscription.formattedString om result.isFinal self.searchFlight (nummer: result.bestTranscription.formattedString)  annars om låt fel = fel skriv ut (fel)

Här är vad den här metoden gör:

  • Initiera a SFSpeechRecognizer instans och kontrollera att taligenkänningen är tillgänglig med en skyddsåtgärd. Om det inte är tillgängligt ställer vi helt enkelt in statusen inte tillgänglig och återvänd. (Standardinitieraren använder standard användarland, men du kan också använda SFSpeechRecognizer (locale :) initialiseraren för att ge en annan plats.)
  • Om taligenkänning är tillgänglig, skapa en SFSpeechURLRecognitionRequest instans genom att skicka den förinspelade ljudadressen.
  • Starta taligenkänningen genom att anropa recognitionTask (med :) metod med den tidigare skapade förfrågan.

Stängningen kommer att kallas flera gånger med två parametrar: ett resultat och ett felobjekt. 

De igenkännare spelar faktiskt filen och försöker känna igen texten stegvis. Av denna anledning kallas stängningen flera gånger. Varje gång det känner igen ett brev eller ett ord eller det gör några korrigeringar, stängs nedläggningen med aktuella objekt. 

De resultat objektet har isFinal egenskapen satt till sann när ljudfilen analyserades fullständigt. I det här fallet startar vi en sökning i vår flygdatakälla för att se om vi kan hitta ett flyg med det erkända flygnummeret. De searchFlight funktionen tar hand om att visa resultatet.

Det sista vi saknar är att åberopa recognizeFile (url :) funktion när mikrofonknappen trycks in:

@IBAction func microphonePressed (_ avsändare: Any) recognizeFile (url: preRecordedAudioURL)

Kör appen på din enhet som kör iOS 10, tryck på mikrofonknappen och du kommer se resultatet. Ljudet "LX40" är inkrementellt erkänt, och flygstatusen visas!

 

Tips: Flygnummeret visas i en UITextView. Som du kanske har märkt, om du aktiverar Flight Number data detektorn i UITextView kan du trycka på den och den aktuella statusen för flygningen visas faktiskt!

Den fullständiga exempelkoden upp till denna punkt kan ses i den förinspelade ljudgrenen i GitHub.

Live Audio Recognition

Låt oss nu se hur man implementerar live taligenkänning. Det kommer att bli lite mer komplicerat än vad vi just gjorde. Du kan återigen ladda ner samma skelettprojekt och följa med.

Vi behöver en ny nyckel i Info.plist fil för att förklara för användaren varför vi behöver tillgång till mikrofonen. Lägg till en ny rad i din Info.plist som visas i bilden.

Vi behöver inte manuellt fråga användaren om tillstånd eftersom iOS kommer att göra det för oss så fort vi försöker få åtkomst till alla mikrofonrelaterade API.

Vi kan återanvända samma kod som vi använde i föregående avsnitt (kom ihåg att importera tal) att begära tillståndet. De viewDidLoad (animerad :) Metoden implementeras exakt som tidigare:

byt SFSpeechRecognizer.authorizationStatus () case .notDetermined: askSpeechPermission () fall .authorized: self.status = .ready fall .denied, .restricted: self.status = .unavailable

Även metoden att fråga användaren om tillstånd är densamma.

func askSpeechPermission () SFSpeechRecognizer.requestAuthorization status i OperationQueue.main.addOperation switch status case .authorized: self.status = .ready default: self.status = .unavailable

Genomförandet av börja filma kommer att bli lite annorlunda. Låt oss först lägga till några nya instansvariabler som kommer att vara till nytta när du hanterar ljudsessionen och taligenkänningsuppgiften.

låt audioEngine = AVAudioEngine () låt speechRecognizer: SFSpeechRecognizer? = SFSpeechRecognizer () låt request = SFSpeechAudioBufferRecognitionRequest () var recognitionTask: SFSpeechRecognitionTask?

Låt oss ta en titt på varje variabel separat:

  • AVAudioEngine används för att bearbeta en ljudström. Vi kommer att skapa en ljudnod och bifoga den till den här motorn så att vi kan uppdateras när mikrofonen tar emot vissa ljudsignaler.
  • SFSpeechRecognizer är samma klass vi har sett i den föregående delen av handledningen, och det tar hand om att erkänna talet. Med tanke på att initialiseraren kan misslyckas och returnera noll, förklarar vi den som valfri för att undvika att krascha vid körning.
  • SFSpeechAudioBufferRecognitionRequest är en buffert som används för att känna igen live-talet. Med tanke på att vi inte har den fullständiga ljudfilen som vi gjorde tidigare behöver vi en buffert för att ange talet som användaren talar.
  • SFSpeechRecognitionTask hanterar nuvarande taligenkänningsuppgift och kan användas för att stoppa eller avbryta det.

När vi har deklarerat alla nödvändiga variabler, låt oss implementera börja filma.

func startRecording () // Inställning ljudmotor och taligenkänningsskydd låter nod = audioEngine.inputNode else return låt recordingFormat = node.outputFormat (forBus: 0) node.installTap (onBus: 0, bufferSize: 1024, format: recordingFormat ) buffert, _ i self.request.append (buffert) // Förbered och starta inspelning av audioEngine.prepare () gör försök audioEngine.start () self.status = .recognizing fånga returutskrift (fel) / / Analysera taligenkänningTask = speechRecognizer? .RecognitionTask (med: request, resultHandler: resultat, fel i om låt resultat = resultat self.flightTextView.text = result.bestTranscription.formattedString self.searchFlight (nummer: result.bestTranscription.formattedString ) annars om låt fel = fel skriv ut (fel))

Detta är kärnkoden för vår funktion. Jag kommer att förklara det steg för steg:

  • Först får vi inputNode av Audioengine. En enhet kan eventuellt ha flera ljudingångar, och här väljer vi den första.
  • Vi berättar inmatningskoden som vi vill övervaka ljudflödet. Det block som vi tillhandahåller kommer att åberopas vid varje mottagen ljudström på 1024 byte. Vi lägger omedelbart ljudbufferten till begäran så att det kan börja erkännandeprocessen.
  • Vi förbereder ljudmotorn för att börja spela in. Om inspelningen startar, ställ in statusen till .känna igen så vi uppdaterar knappikonen för att låta användaren veta att deras röst spelas in.
  • Låt oss tilldela det returnerade objektet från speechRecognizer.recognitionTask (med: resultHandler :) till recognitionTask variabel. Om godkännandet är framgångsrikt söker vi flygningen i vår datakälla och uppdaterar användargränssnittet. 

Funktionen att avbryta inspelningen är lika enkel som att stoppa ljudmotorn, ta bort kranen från ingångskoden och avbryta igenkänningsuppgiften.

func cancelRecording () audioEngine.stop () om låt nod = audioEngine.inputNode node.removeTap (onBus: 0) recognitionTask? .cancel ()

Vi behöver nu bara starta och stoppa inspelningen. Ändra microphonePressed metod enligt följande:

@IBAction func mikrofonPressed () switch status case .ready: startRecording () status = .recognizing case.recognizing: cancelRecording () status = .ready default: break

Beroende på strömmen status, Vi startar eller stoppar taligenkänningen.

Bygg och kör appen för att se resultatet. Försök att stava några av de angivna flygnummer och du bör se dess status visas.

 

Återigen kan exemplet koden ses i live-ljudgrenen på GitHub.

Bästa praxis

Taligenkänning är ett mycket kraftfullt API som Apple levererade till iOS-utvecklare som riktar sig mot iOS 10. Det är helt gratis att använda, men kom ihåg att det inte är obegränsat i användningen. Det är begränsat till ungefär en minut för varje taligenkänningsuppgift, och din app kan också bli störd av Apples servrar om den kräver för mycket beräkning. Av dessa skäl har det stor inverkan på nätverkstrafik och strömförbrukning. 

Se till att dina användare är korrekt instruerade om hur du använder taligenkänning och vara så transparenta som möjligt när du spelar in sin röst. 

Recap

I den här handledningen har du sett hur du använder snabb, exakt och flexibelt taligenkänning i IOS 10. Använd det till din fördel att ge dina användare en ny sätt att interagera med din app och förbättra tillgängligheten samtidigt. 

Om du vill lära dig mer om att integrera Siri i din app, eller om du vill ta reda på några av de andra coola utvecklarfunktionerna i IOS 10, kolla Markus Mühlberger kurs.

Kolla även några av våra andra gratis handledning på IOS 10-funktioner.