Speech Recognition (Speech-to-Text)

API Reference: SpeechRecognizer

SpeechRecognizer provides access to the speech recognition service.

Offline Speech Recognition On Android

To use offline speech recognizer, language package must be installed. If not installed, the speech recognizer throws SpeechRecognizer.Error.SERVER error. This screenshot is taken from a device that supports English and Spanish speech recognition.

onFinish Callback

onFinish callback is triggered in a few seconds after starting Speech Recognizer on Android devices. But it requires much more time on iOS devices.

onResult Callback

onResult is fired when partial recognition results are available. This callback can also be fired different number of times in Android and iOS. There is no guarantee onResult callback will be fired on each word.

Network changes on iOS

When the network changes, speech recognizer may not available. The speech recognizer throws SpeechRecognizer.Error.NETWORK error in this case.

Supported Locales on iOS

For iOS, you should check your current locale is supported from isLocaleSupported function. if doesn't support your current locale, you must set locale parameter in constructor function.

Android Permissions

For Android, RECORD_AUDIO permission is required for using SpeechRecognizer. Add the following permission to AndroidManifest.xml file in necessary, also take a look at Application.android.Permissions.RECORD_AUDIO.

See also Android official documentation about this permission.

iOS Permissions

Permission keys must be added info.plist for iOS

NSSpeechRecognitionUsageDescription $(PRODUCT_NAME) Speech Recognition access for development

NSMicrophoneUsageDescription $(PRODUCT_NAME) Microphone access for development

TypeScript code blocks include examples of how to implement, override and components within the theme. You can create page with the UI Editor to make your page compatible with theming and then you can implement themable components programmatically. Once the page is created with the UI Editor, it generates a class under scripts/generated/pages. You can then extend that class with the following TypeScript classes.

TypeScript
JavaScript
TypeScript
import PageSampleDesign from 'generated/pages/pageSample';
import FlexLayout = require('sf-core/ui/flexlayout');
import Application = require('sf-core/application');
import System = require('sf-core/device/system');
import Button = require("sf-core/ui/button");
import Label = require("sf-core/ui/label");
import SpeechRecognizer = require("sf-core/speechrecognizer");
//You should create new Page from UI-Editor and extend with it.
export default class Sample extends PageSampleDesign {
myButton: Button;
myLabel: Label;
myFlexLayout: FlexLayout;
constructor() {
super();
// Overrides super.onShow method
this.onShow = onShow.bind(this, this.onShow.bind(this));
// Overrides super.onLoad method
this.onLoad = onLoad.bind(this, this.onLoad.bind(this));
this.layout.flexDirection = FlexLayout.FlexDirection.ROW;
this.layout.justifyContent = FlexLayout.JustifyContent.CENTER;
this.layout.alignItems = FlexLayout.AlignItems.CENTER;
this.layout.flexWrap = FlexLayout.FlexWrap.WRAP;
}
startSpeechRecognizer(): void {
SpeechRecognizer.start({
locale: "en_US",
onResult: (result) => {
this.myLabel.text = result;
},
onFinish: (result) => {
this.myButton.text = "Start Recording";
alert("Finish : " + result);
},
onError: (error) => {
this.myButton.text = "Start Recording";
alert("Error : " + error);
}
});
}
}
/**
* @event onShow
* This event is called when a page appears on the screen (everytime).
* @param {function} superOnShow super onShow function
* @param {Object} parameters passed from Router.go function
*/
function onShow(superOnShow: () => void) {
const { headerBar } = System.OS === "Android" ? this : this.parentController;
superOnShow();
Application.statusBar.visible = true;
headerBar.visible = true;
headerBar.leftItemEnabled = false;
}
/**
* @event onLoad
* This event is called once when page is created.
* @param {function} superOnLoad super onLoad function
*/
function onLoad(superOnLoad: () => void) {
superOnLoad();
this.myFlexLayout = new FlexLayout();
this.myButton = new Button({
text: "START SPEECH",
onPress: () => {
if (!SpeechRecognizer.isRunning()) {
this.myButton.text = "Stop Recording";
if (System.OS === "iOS") {
this.startSpeechRecognizer();
}
else if (System.OS === "Android") {
const RECORD_AUDIO_CODE = 1002;
Application.android.requestPermissions(RECORD_AUDIO_CODE, Application.Android.Permissions.RECORD_AUDIO);
Application.android.onRequestPermissionsResult = (e) => {
if (e.requestCode === RECORD_AUDIO_CODE && e.result) {
this.startSpeechRecognizer();
}
};
}
}
else {
this.myButton.text = "Start Recording";
SpeechRecognizer.stop();
}
}
});
this.layout.addChild(this.myFlexLayout, "myFlexLayout", ".sf-flexLayout", {
flexGrow: 1,
flexProps: {
flexDirection: "COLUMN"
}
});
this.myLabel = new Label({
text: "Result is here"
});
this.myFlexLayout.addChild(this.myButton, "myButton", ".sf-button", {
width: null,
height: null,
flexGrow: 1
});
this.myFlexLayout.addChild(this.myLabel, "myLabel", ".sf-label", {
width: null,
height: null,
flexGrow: 3
});
}
JavaScript
const Page = require("sf-core/ui/page");
const FlexLayout = require("sf-core/ui/flexlayout");
const Button = require("sf-core/ui/button");
const Label = require("sf-core/ui/label");
const SpeechRecognizer = require("sf-core/speechrecognizer");
const Application = require("sf-core/application");
const System = require("sf-core/device/system");
const extend = require("js-base/core/extend");
var Page1 = new extend(Page)(
function Page1(_super, params) {
_super(this, {
onShow: function() {},
onLoad: function() {
var myFlexLayout = new FlexLayout({
flexGrow: 1,
flexDirection: FlexLayout.FlexDirection.COLUMN
});
var myButton = new Button({
flexGrow: 1,
text: "START SPEECH",
onPress: function() {
if (!SpeechRecognizer.isRunning()) {
myButton.text = "Stop Recording";
if (System.OS === "iOS") {
startSpeechRecognizer();
}
else if (System.OS === "Android") {
const RECORD_AUDIO_CODE = 1002;
Application.android.requestPermissions(RECORD_AUDIO_CODE, Application.android.Permissions.RECORD_AUDIO);
Application.android.onRequestPermissionsResult = function(e) {
if (e.requestCode === RECORD_AUDIO_CODE && e.result) {
startSpeechRecognizer();
}
};
}
}
else {
myButton.text = "Start Recording";
SpeechRecognizer.stop();
}
}
});
var myLabel = new Label({
flexGrow: 3,
text: "Result is here"
});
myFlexLayout.addChild(myButton);
myFlexLayout.addChild(myLabel);
function startSpeechRecognizer() {
SpeechRecognizer.start({
locale : "en_US",
onResult: function(result) {
myLabel.text = result;
},
onFinish: function(result) {
myButton.text = "Start Recording";
alert("Finish : " + result);
},
onError: function(error) {
myButton.text = "Start Recording";
alert("Error : " + error);
}
});
}
this.headerBar.leftItemEnabled = false;
this.layout.addChild(myFlexLayout);
}
});
}
);
module.exports = Page1;