De API voor spraakherkenning gebruiken in iOS 10

Wat je gaat creëren

Invoering

Siri is een belangrijk kenmerk van iOS sinds het in 2011 werd geïntroduceerd. Nu biedt iOS 10 nieuwe functies waarmee ontwikkelaars met Siri kunnen communiceren. In het bijzonder zijn nu twee nieuwe frameworks beschikbaar: Speech en SiriKit. 

Vandaag gaan we het Speech-framework bekijken, waarmee we audio eenvoudig in tekst kunnen vertalen. U leert hoe u een real-life app bouwt die de API voor spraakherkenning gebruikt om de status van een vlucht te controleren.

Als je meer wilt weten over SiriKit, heb ik dit behandeld in mijn Create SiriKit Extensions in iOS 10-zelfstudie. Kijk voor meer informatie over de andere nieuwe functies voor ontwikkelaars in iOS 10 op de cursus van Markus Mühlberger, hier op Envato Tuts+.

Gebruik

Spraakherkenning is het proces waarbij live of vooraf opgenomen audio naar getranscribeerde tekst wordt vertaald. Sinds Siri werd geïntroduceerd in iOS 5, is er een microfoonknop op het systeemtoetsenbord geplaatst waarmee gebruikers eenvoudig kunnen dicteren. Deze functie kan worden gebruikt met elke UIKit-tekstinvoer en u hoeft geen extra code te schrijven die verder gaat dan wat u zou schrijven om een ​​standaard tekstinvoer te ondersteunen. Het is echt snel en gemakkelijk te gebruiken, maar het heeft enkele beperkingen:

  • Het toetsenbord is altijd aanwezig tijdens het dicteren.
  • De taal kan niet door de app zelf worden aangepast.
  • De app kan niet worden gewaarschuwd wanneer het dictaat begint en eindigt.

Om ontwikkelaars in staat te stellen meer aanpasbare en krachtige applicaties met dezelfde dicteertechnologie als Siri te bouwen, creëerde Apple het Speech-framework. Hiermee kan elk apparaat met iOS 10 audio vertalen naar tekst in meer dan 50 talen en dialecten.

Deze nieuwe API is veel krachtiger omdat deze niet alleen een eenvoudige transcriptieservice biedt, maar ook alternatieve interpretaties biedt van wat de gebruiker mogelijk heeft gezegd. U kunt bepalen wanneer een dictaat moet worden gestopt, u ​​kunt resultaten weergeven terwijl uw gebruiker spreekt en het spraakherkenningsprogramma past zich automatisch aan aan de gebruikersvoorkeuren (taal, woordenschat, namen, etc.). 

Een interessante functie is ondersteuning voor het overschrijven van vooraf opgenomen audio. Als u bijvoorbeeld een Instant Messaging-app aan het bouwen bent, kunt u deze functie gebruiken om de tekst van nieuwe audioberichten te transcriberen.

Opstelling

Allereerst moet u de gebruiker om toestemming vragen om zijn stem naar Apple te verzenden voor analyse. 

Afhankelijk van het apparaat en de taal die moet worden herkend, kan iOS op transparante wijze besluiten om de audio op het apparaat zelf te transcriberen of, als lokale spraakherkenning niet beschikbaar is op het apparaat, zal iOS de servers van Apple gebruiken om het werk te doen. 

Daarom is meestal een actieve internetverbinding vereist voor spraakherkenning. Ik zal u laten zien hoe u de beschikbaarheid van de service zeer snel kunt controleren.

Er zijn drie stappen om spraakherkenning te gebruiken:

  • Leg uit: vertel uw gebruiker waarom u toegang wilt tot zijn stem.
  • Autoriseren: vraag expliciet toestemming om toegang te krijgen tot hun stem.
  • Verzoek: laad een vooraf opgenomen audio van schijf met behulp van SFSpeechURLRecognitionRequest, of stream live audio met SFSpeechAudioBufferRecognitionRequest en verwerk de transcriptie.

Als je meer wilt weten over het Speech-framework, bekijk dan WWDC 2016 Session 509. Je kunt ook de officiële documentatie lezen.

Voorbeeld

Ik laat je nu zien hoe je een real-life app bouwt die gebruik maakt van de spraakherkennings-API. We gaan een kleine app voor het volgen van vluchten bouwen waarin de gebruiker eenvoudigweg een vluchtnummer kan zeggen en de app zal de huidige status van de vlucht weergeven. Ja, we gaan een kleine assistent zoals Siri bouwen om de status van een vlucht te controleren!

In de GitHub-repo van de zelfstudie heb ik een skeletproject geleverd met een eenvoudige gebruikersinterface die ons zal helpen bij deze zelfstudie. Download en open het project in Xcode 8.2 of hoger. Beginnend met een bestaande gebruikersinterface kunnen we ons richten op de API voor spraakherkenning.

Bekijk de lessen in het project. UIViewController + Style.swift bevat de meeste code die verantwoordelijk is voor het updaten van de gebruikersinterface. De voorbeeldgegevensbron van de vluchten die in de tabel worden weergegeven, wordt aangegeven in FlightsDataSource.swift.

Als u het project uitvoert, ziet het er als volgt uit.

Nadat de gebruiker op de microfoonknop heeft gedrukt, willen we de spraakherkenning starten om het vluchtnummer te transcriberen. Dus als de gebruiker 'LX40' zegt, willen we graag de informatie over de gate en de huidige status van de vlucht weergeven. Om dit te doen, zullen we een functie bellen om automatisch de vlucht op te zoeken in een gegevensbron en de status van de vlucht te tonen. 

We gaan eerst onderzoeken hoe je kunt transcriberen van vooraf opgenomen audio. Later leren we hoe we de interessantere live spraakherkenning kunnen implementeren.

Laten we beginnen met het opzetten van het project. Open de Info.plist bestand en voeg een nieuwe rij toe met de uitleg die aan de gebruiker wordt getoond wanneer hem toestemming wordt gevraagd om toegang te krijgen tot zijn stem. De nieuw toegevoegde rij is blauw gemarkeerd in de volgende afbeelding.

Zodra dit is gebeurd, open ViewController.swift. Let niet op de code die al in deze klasse staat; het zorgt alleen voor het updaten van de gebruikersinterface voor ons.

De eerste stap met elk nieuw framework dat u wilt gebruiken, is om het bovenaan het bestand te importeren.

Spraak importeren

Om het toestemmingsvenster voor de gebruiker weer te geven, voegt u deze code toe in de viewDidLoad (geanimeerde :) methode:

schakel SFSpeechRecognizer.authorizationStatus () case .notDetermined: askSpeechPermission () case. geautorized: self.status = .ready case .denied, .restricted: self.status = .unavailable

De staat variabele zorgt ervoor dat de gebruikersinterface wordt gewijzigd om de gebruiker te waarschuwen dat spraakherkenning niet beschikbaar is voor het geval er iets misgaat. We gaan een nieuwe status toewijzen aan dezelfde variabele elke keer dat we de gebruikersinterface zouden willen wijzigen.

Als de app de gebruiker nog geen toestemming heeft gevraagd, is de autorisatiestatus niet bepaald, en we noemen het askSpeechPermission methode om het te vragen zoals gedefinieerd in de volgende stap.

Je zou moeten faal altijd elegant als een specifieke functie niet beschikbaar is. Het is ook heel belangrijk om altijd te doen communiceren met de gebruiker wanneer u hun stem opneemt. Probeer nooit hun stem te herkennen zonder eerst de gebruikersinterface bij te werken en uw gebruiker hiervan op de hoogte te stellen.

Hier is de implementatie van de functie om de gebruiker om toestemming te vragen.

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

We roepen het requestAuthorization methode om het privacy-verzoek voor spraakherkenning weer te geven dat we hebben toegevoegd aan de Info.plist. We schakelen vervolgens over naar de hoofdthread in het geval dat de sluiting werd aangeroepen op een andere thread. We willen de gebruikersinterface alleen via de hoofdthread bijwerken. We wijzen het nieuwe toe staat om de microfoonknop bij te werken om de gebruiker de beschikbaarheid (of niet) van spraakherkenning te signaleren.

Pre-Recorded Audio Recognition

Voordat we de code schrijven om vooraf opgenomen audio te herkennen, moeten we de URL van het audiobestand vinden. Controleer in de projectnavigator of u een bestand met de naam hebt LX40.m4a. Ik heb dit bestand zelf opgenomen met de Voice Memo-app op mijn iPhone door "LX40" te zeggen. We kunnen eenvoudig controleren of we een correcte transcriptie van de audio krijgen.

Bewaar de audiobestands-URL in een eigenschap:

var preRecordedAudioURL: URL = return Bundle.main.url (for Resource: "LX40", withExtension: "m4a")!  ()

Het is tijd om eindelijk de kracht en eenvoud van het Speech-framework te zien. Dit is de code die alle spraakherkenning voor ons doet:

func recognitionFile (url: URL) guard let recognizer = SFSpeechRecognizer (), recognizer.isAvailable else return let request = SFSpeechURLRecognitionRequest (url: url) recognizer.recognitionTask (with: request) result, fout in bewaker laat herkenner = SFSpeechRecognizer (), recognizer.isBeschikbaar anders return self.status = .unavailable als resultaat laten zien = resultaat self.flightTextView.text = result.bestTranscription.formattedString if result.isFinal self.searchFlight (number: result.bestTranscription.formattedString)  else if let error = error print (error)

Dit is wat deze methode doet:

  • Initialiseren a SFSpeechRecognizer bijvoorbeeld en controleer of de spraakherkenning beschikbaar is met een bewakingsinstructie. Als het niet beschikbaar is, stellen we gewoon de status in niet beschikbaar En terugkomen. (De standaardinitialisatie gebruikt de standaardgebruikerslandinstelling, maar u kunt ook de SFSpeechRecognizer (locale :) initializer om een ​​andere locale te bieden.)
  • Als spraakherkenning beschikbaar is, maakt u een SFSpeechURLRecognitionRequest bijvoorbeeld door de vooraf opgenomen audio-URL door te geven.
  • Start de spraakherkenning door de recognitionTask (met :) methode met het eerder gemaakte verzoek.

De sluiting wordt meerdere keren aangeroepen met twee parameters: een resultaat en een foutobject. 

De herkenner speelt in feite het bestand en probeert de tekst stapsgewijs te herkennen. Om deze reden wordt de sluiting meerdere keren genoemd. Telkens wanneer een letter of een woord wordt herkend of er enkele correcties worden aangebracht, wordt de sluiting aangeroepen met actuele objecten. 

De resultaat object heeft de isFinal eigenschap ingesteld op true wanneer het audiobestand volledig is geanalyseerd. In dit geval starten we een zoekopdracht in onze vluchtgegevensbron om te zien of we een vlucht met het erkende vluchtnummer kunnen vinden. De searchFlight functie zorgt voor weergave van het resultaat.

Het laatste wat we missen is het aanroepen van de recognizeFile (url :) functie wanneer de microfoonknop wordt ingedrukt:

@IBAction func microphonePressed (_ sender: Any) recognisefile (url: preRecordedAudioURL)

Voer de app uit op uw apparaat met iOS 10, druk op de microfoonknop en u ziet het resultaat. De audio "LX40" wordt stapsgewijs herkend en de vluchtstatus wordt weergegeven!

 

Tip: het vluchtnummer wordt weergegeven in een UITextView. Zoals je misschien hebt gemerkt, als je de datanaald van het vluchtnummer in de UITextView inschakelt, kun je erop drukken en de huidige status van de vlucht wordt daadwerkelijk weergegeven!

De volledige voorbeeldcode tot aan dit punt kan worden bekeken in de pre-recorded-audio-vertakking in GitHub.

Live-audio-herkenning

Laten we nu kijken hoe we live spraakherkenning kunnen implementeren. Het zal een beetje ingewikkelder worden in vergelijking met wat we net deden. U kunt hetzelfde skeletproject opnieuw downloaden en volgen.

We hebben een nieuwe sleutel nodig in de Info.plist bestand om aan de gebruiker uit te leggen waarom we toegang tot de microfoon nodig hebben. Voeg een nieuwe rij toe aan uw Info.plist zoals getoond in de afbeelding.

We hoeven de gebruiker niet handmatig toestemming te vragen omdat iOS dit voor ons zal doen zodra we toegang proberen te krijgen tot een microfoon-gerelateerde API.

We kunnen dezelfde code hergebruiken die we in de vorige sectie hebben gebruikt (vergeet niet Spraak importeren) om toestemming te vragen. De viewDidLoad (geanimeerde :) methode is precies zoals voorheen geïmplementeerd:

schakel SFSpeechRecognizer.authorizationStatus () case .notDetermined: askSpeechPermission () case. geautorized: self.status = .ready case .denied, .restricted: self.status = .unavailable

Ook is de methode om de gebruiker toestemming te vragen hetzelfde.

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

De implementatie van start met opnemen zal een beetje anders zijn. Laten we eerst een paar nieuwe instantievariabelen toevoegen die van pas zullen komen bij het beheren van de audiosessie en de spraakherkenningstaak.

laat audioEngine = AVAudioEngine () laat speechRecognizer: SFSpeechRecognizer? = SFSpeechRecognizer () laatverzoek = SFSpeechAudioBufferRecognitionRequest () var recognitionTask: SFSpeechRecognitionTask?

Laten we elke variabele afzonderlijk bekijken:

  • AVAudioEngine wordt gebruikt om een ​​audiostream te verwerken. We zullen een audioknooppunt maken en dit koppelen aan deze engine, zodat we kunnen worden bijgewerkt wanneer de microfoon een aantal audiosignalen ontvangt.
  • SFSpeechRecognizer is dezelfde klas die we hebben gezien in het vorige deel van de tutorial, en het zorgt voor de herkenning van de speech. Aangezien de initializer kan mislukken en niets teruggeven, geven we aan dat deze de optionele is om crashen tijdens runtime te voorkomen.
  • SFSpeechAudioBufferRecognitionRequest is een buffer die wordt gebruikt om de live speech te herkennen. Aangezien we niet het volledige audiobestand hebben zoals we eerder deden, hebben we een buffer nodig om de spraak toe te wijzen als de gebruiker spreekt.
  • SFSpeechRecognitionTask beheert de huidige spraakherkenningstaak en kan worden gebruikt om deze te stoppen of te annuleren.

Zodra we alle vereiste variabelen hebben verklaard, laten we het implementeren start met opnemen.

func startRecording () // Setup audio engine en spraakherkenner bewaar knooppunt = audioEngine.inputNode else return laat recordingFormat = node.outputFormat (forBus: 0) node.installTap (onBus: 0, bufferSize: 1024, format: recordingFormat ) buffer, _ in self.request.append (buffer) // Bereid u voor en begin met het opnemen van audioEngine.prepare () do try audioEngine.start () self.status = .recognizing catch return print (error) / / Analyseer de spraakherkenningTask = speechRecognizer? .RecognitionTask (met: request, resultHandler: result, error in if let result = resultaat self.flightTextView.text = result.bestTranscription.formattedString self.searchFlight (number: result.bestTranscription.formattedString ) else if let error = error print (error))

Dit is de kerncode van onze functie. Ik zal het stap voor stap uitleggen:

  • Eerst krijgen we de inputNode van de Audioengine. Een apparaat kan mogelijk meerdere audio-ingangen hebben en hier selecteren we de eerste.
  • We vertellen het invoerknooppunt dat we de audiostream willen controleren. Het blok dat we bieden, wordt aangeroepen voor elke ontvangen audiostream van 1024 bytes. We voegen de audiobuffer onmiddellijk toe aan de verzoek zodat het herkenningsproces kan starten.
  • We bereiden de audio-engine voor om de opname te starten. Als de opname met succes start, stelt u de status in op .herkennen zodat we het knoppictogram bijwerken om de gebruiker te laten weten dat zijn stem wordt opgenomen.
  • Laten we het geretourneerde object toewijzen speechRecognizer.recognitionTask (met: resultHandler :) naar de recognitionTask variabel. Als de herkenning succesvol is, zoeken we de vlucht in onze gegevensbron en werken we de gebruikersinterface bij. 

De functie om de opname te annuleren is net zo eenvoudig als het stoppen van de audiomachine, het verwijderen van de tik van het ingangsknooppunt en het annuleren van de herkenningstaak.

func cancelRecording () audioEngine.stop () if let node = audioEngine.inputNode node.removeTap (onBus: 0) recognitionTask? .cancel ()

We hoeven nu alleen maar de opname te starten en te stoppen. Wijzig de microphonePressed methode als volgt:

@IBAction func microphonePressed () switchstatus case .ready: startRecording () status =. Herkenning van case .herkenning: cancelRecording () status = .ready default: break

Afhankelijk van de stroom staat, we starten of stoppen de spraakherkenning.

Bouw en voer de app uit om het resultaat te bekijken. Probeer een van de vermelde vluchtnummers te spellen en u zou de status ervan moeten zien verschijnen.

 

Nogmaals, de voorbeeldcode kan worden bekeken in de live-audiotak op GitHub.

Beste praktijken

Spraakherkenning is een zeer krachtige API die Apple heeft verstrekt aan iOS-ontwikkelaars die gericht zijn op iOS 10. Het is volledig gratis te gebruiken, maar onthoud dat het niet onbeperkt is in gebruik. Het is gelimiteerd tot ongeveer één minuut voor elke spraakherkenningstaak en uw app kan ook worden ingeklemd door de servers van Apple als het te veel berekeningen vereist. Om deze redenen heeft dit een grote invloed op het netwerkverkeer en het stroomverbruik. 

Zorg ervoor dat uw gebruikers correct zijn geïnstrueerd over het gebruik van spraakherkenning en wees zo transparant mogelijk wanneer u hun stem opneemt. 

Samenvatting

In deze zelfstudie hebt u gezien hoe u snelle, nauwkeurige en flexibele spraakherkenning in iOS 10 kunt gebruiken. Gebruik het in uw eigen voordeel om uw gebruikers een nieuwe manier van interactie met uw app te bieden en tegelijkertijd de toegankelijkheid te verbeteren. 

Als je meer wilt weten over de integratie van Siri in je app, of als je meer wilt weten over de andere coole ontwikkelaarstoepassingen van iOS 10, ga dan naar de cursus van Markus Mühlberger.

Bekijk ook enkele van onze andere gratis tutorials over iOS 10-functies.