Description
ezSTT ANE
AIR Native Extension for Android & iOS mobile projects
Version 1.5.0
Bring the power of voice recognition to your mobile projects. With ezSTT ANE, your application can ear and understand your users.
Imagine even more interactive services
Apple and Google works with cloud services for Speech Recognition.
This extension use the online Speech Recognition service provided by Google and Apple.
In a few lines of code, ezSTT ANE will give natural recognition of the language to your games or applications.
How to test ezSTT ANE
First, you need to download or fork ezSTT AIR Native Extension project on GitHub.
Link the extension with your project
The ANE library (ezSTT.ane) is located in the ‘bin’ folder.
You should add it to your application project’s build path and make sure to package it with your app.
For more information about this process, see :
- How to use ANE with Adobe Flash Builder 4.7
- How to use ANE with Adobe Flash CS6
- How to use ANE with Adobe Flash CC
- How to use ANE with Adobe Animate CC
- How to use ANE with IntelliJ IDEA
- Under File > Project Structure… > Modules make sure you have one module for each of your target platforms
- Under File > Project Structure… > General make sure your project type is ActionScript (or Flex) for AIR mobile platform. You can use
Change..
to have the correct type. - Each module should target either Android or iOS
- Depending on your target, add the correct ANE in the
Dependencies
tab by using + > New Library… - On each of the platform tags you can generate a custom app descriptor or use the IDE generated one. You can use one for all platforms, or create one for each platform.
- Only the generated one will include the extension IDs automatically
- The application descriptor already contains the Android manifest and/or the iOS plist inside. You can set it up exactly like for the Flash Builder when using the custom app descriptor.
- If you use the custom app descriptor, check that the right extension ID is added under
<extensions>
In your application-app.xml file, you need to add the following lines :
1 2 3 |
<extensions> <extensionID>com.fabricemontfort.air.ezSTT</extensionID> </extensions> |
In the same file, you have to add the following line in the iOS section :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<!-- iOS specific capabilities --> <iPhone> <!-- A list of plist key/value pairs to be added to the application Info.plist --> <InfoAdditions> <![CDATA[ <key>UIDeviceFamily</key> <array> <!-- iPhone and iPod touch devices --> <string>1</string> <!-- iPad devices --> <string>2</string> </array> <!-- IMPORTANT BEGIN --> <!-- A feature request to translate Permissions Strings for iOS here : --> <!-- https://tracker.adobe.com/#/view/AIR-4198336 --> <!-- Please vote for it --> <key>NSSpeechRecognitionUsageDescription</key> <string>NEED VOICE RECOGNITION</string> <key>NSMicrophoneUsageDescription</key> <string>NEED MICROPHONE</string> <key>MinimumOSVersion</key> <string>10.0</string> <!-- IMPORTANT END --> ]]> </InfoAdditions> <requestedDisplayResolution>high</requestedDisplayResolution> </iPhone> |
In the same file (again), you have to ensure you request proper permissions in the Android section :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<!-- Android specific tags that get passed to AndroidManifest.xml file. --> <android> <manifestAdditions> <![CDATA[ <manifest android:installLocation="auto"> <!-- IMPORTANT BEGIN --> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.RECORD_AUDIO"/> <!-- IMPORTANT END --> </manifest> ]]> </manifestAdditions> </android> |
Type a few lines of code
Now you’ll know what easy means.
Import, instanciate, add event listeners, test and start to use. Everything is done in a few lines of code!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
import com.fabricemontfort.air.ezSTT; import com.fabricemontfort.air.ezstt.STTEvent; import com.fabricemontfort.air.ezstt.languages; var stt:ezSTT = ezSTT.instance(); public function onAuth(event:STTEvent):void { trace (event.message); if (stt.isAuthorized()) { stt.removeEventListener(STTEvent.AUTH, onAuth); stt.addEventListener(STTEvent.FINAL, onFinal); stt.setLanguage(languages.FR); stt.start(); } } public function onFinal(event:STTEvent):void { // Best result from Google / Apple stt.removeEventListener(STTEvent.FINAL, onFinal); trace (event.message); } if (stt.isSupported()) { if (stt.isAuthorized()) { stt.debug = true; stt.addEventListener(STTEvent.FINAL, onFinal); stt.setLanguage(languages.FR); stt.start(); } else { stt.addEventListener(STTEvent.AUTH, onAuth); stt.askUserAuthorization(); } } |
With the setLanguage function :
On both systems, this ANE use the Speech Recognition Cloud API (juste like Siri and Google Agent). You have to ensure you have a connexion to internet.
If you want to do offline Speech Recognition, you have to ensure that appropriate language packs are installed (In Settings > Languages > Speech Recognition > Offline). There is actually no way to do this programmaticaly.
On both systems, this ANE supports: English, French, Italian, Spanish, Deutsch, Chinese, Japanese, Russian, Korean, Portuguese, Czech, Dutch, Polish, Swedish, Turkish (the exact same languages than AIR 24 Runtime)
With the forceLanguage function :
On both systems, you have to ensure a proper STT engine is installed and selected by default to enforce a specific language. This function is EXPERIMENTAL.
Minimum OS & SDK version
In order to work, the AIR SDK and the device operating system must be at least:
- AIR 25
- Android 5.0
- iOS 10.0
If device operating system doesn’t match the minimum requierements, “isSupported” method will always return false.
Sample app
There is a complete Feathers 3.3.0 & AIR 26 sample project in the ‘example’ folder. It was created with Flash Builder 4.7.
Feel free to test it and adapt it for your own needs.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
<?xml version="1.0" encoding="utf-8"?> <f:Application xmlns:f="library://ns.feathersui.com/mxml" xmlns:fx="http://ns.adobe.com/mxml/2009" theme="feathers.themes.MetalWorksMobileTheme"> <fx:Script> <![CDATA[ import com.fabricemontfort.air.ezSTT; import com.fabricemontfort.air.ezstt.STTEvent; import com.fabricemontfort.air.ezstt.languages; import starling.events.Event; private static const OUCH:String = "Not supported"; private static const AUTH:String = "Ask user permissions"; private static const START:String = "Start listening"; private static const STOP:String = "Stop listening"; private var stt:ezSTT = ezSTT.instance; override protected function initialize():void { super.initialize(); stt.debug = false; if (stt.isSupported()) { if (stt.isAuthorized()) { stt.addEventListener(STTEvent.PARTIAL, onSTTResult); stt.addEventListener(STTEvent.FINAL, onSTTResult); stt.addEventListener(STTEvent.VOL, onSTTVolume); stt.addEventListener(STTEvent.STOP, onSTTStop); actionButton.label = START; } else { stt.addEventListener(STTEvent.AUTH, onAuth); actionButton.label = AUTH; } } else { actionButton.label = OUCH; } } private function onSTTResult(event:STTEvent):void { trace(event.message); resultLabel.text = event.message; } private function onSTTVolume(event:STTEvent):void { volumeBar.value = parseInt(event.message); } private function onSTTStop(event:STTEvent):void { actionButton.label = START; volumeBar.value = 0; } private function onAuth(event:STTEvent):void { trace(event.message); if (stt.isAuthorized()) { stt.removeEventListener(STTEvent.AUTH, onAuth); stt.addEventListener(STTEvent.PARTIAL, onSTTResult); stt.addEventListener(STTEvent.FINAL, onSTTResult); stt.addEventListener(STTEvent.VOL, onSTTVolume); stt.addEventListener(STTEvent.STOP, onSTTStop); actionButton.label = START; } } private function actionButton_triggeredHandler(event:Event):void { switch (actionButton.label) { case AUTH: { stt.askUserAuthorization(); break; } case START: { stt.start(); actionButton.label = STOP; break; } case STOP: { stt.stop(); actionButton.label = START; break; } } } private function langPickerList_changeHandler(event:Event):void { stt.setLanguage(langPickerList.selectedItem.code); } private function forceLangTextInput_changeHandler(event:Event):void { stt.forceLanguage(forceLangTextInput.text); } ]]> </fx:Script> <f:layout> <f:VerticalLayout gap="10" padding="10"/> </f:layout> <fx:Declarations> <f:VerticalLayoutData id="fitScreen" percentWidth="100" percentHeight="100"/> <f:VerticalLayoutData id="fitWidth" percentWidth="100"/> <f:ListCollection id="langListCollection"> <fx:Object label="English" code="{languages.EN}"/> <fx:Object label="French" code="{languages.FR}"/> <fx:Object label="German" code="{languages.DE}"/> <fx:Object label="Italian" code="{languages.IT}"/> <fx:Object label="Spanish" code="{languages.ES}"/> <fx:Object label="Chinese" code="{languages.ZH}"/> <fx:Object label="Japanese" code="{languages.JA}"/> <fx:Object label="Russian" code="{languages.RU}"/> <fx:Object label="Korean" code="{languages.KO}"/> <fx:Object label="Portuguese" code="{languages.PT}"/> <fx:Object label="Czech" code="{languages.CS}"/> <fx:Object label="Dutch" code="{languages.NL}"/> <fx:Object label="Polish" code="{languages.PL}"/> <fx:Object label="Swedish" code="{languages.SV}"/> <fx:Object label="Turkish" code="{languages.TR}"/> </f:ListCollection> </fx:Declarations> <f:Label id="resultLabel" wordWrap="true" layoutData="{fitScreen}"/> <f:ProgressBar id="volumeBar" minimum="0" maximum="12" layoutData="{fitWidth}"/> <f:PickerList id="langPickerList" change="langPickerList_changeHandler(event)" focusPadding="20" dataProvider="{langListCollection}" layoutData="{fitWidth}"/> <f:Label id="forceLangLabel" text="TEST A COUNTRY CODE (AT YOUR OWN RISKS)" layoutData="{fitWidth}"/> <f:TextInput id="forceLangTextInput" padding="20" change="forceLangTextInput_changeHandler(event)" layoutData="{fitWidth}"/> <f:Button id="actionButton" padding="20" triggered="actionButton_triggeredHandler(event)" layoutData="{fitWidth}"/> </f:Application> |
Documentation
You can access the complete asdoc in the ‘doc’ folder.
Author
ezSTT ANE is developped by Fabrice Montfort. All rights are reserved.
Showcase
Feel free to ask for an Ad in this section.
Buy a licence
If you want to use in a production project, you have to purchase the full version.
You will be able to download an archive with the full production version from your account on this website after your payment has been validated.
This is an ANNUAL LICENSE, valid for all your projects. You will benefit from all updates without restrictions during 365 days after your purchase. After that delay, you’ll have to buy a new license.
Support
If you have any question, comment, or suggestion, you can leave me a message on Github. I’ll give you a quick answer.
I made the choice to centralize all trade questions and answers on GitHub so that they can serve all users.
Updates
1.5.0 – Work with AIR 33, iOS 13 and Android 64bit – Works well in iOS and Android simulators
1.0.2 – Add Timeout for iOS – Work with AIR 30, iOS 11.3 – Bug resolved for AIR Simulator on Desktop
1.0.1 – Works closer with ezSpeech
1.0.0 – First public release