In this tutorial, we’ll look at how to give your Android device a voice using a Text to Speech (TTS) library. Whether you’re developing applications for the visually impaired, or just want to liven up your Android system, giving your project a voice can be an interesting feature. To do this, we’re going to integrate the react-native-tts library into an Android application developed with React Native.
Hardware
- Android device
- Computer for programming
- USB cable to connect Android device to PC
React Native project configuration
The react-native-tts text-to-speech library lets you use the voices, or text-to-speech models, available on your Android device to read text.
npm install react-native-tts --save
We use a drop-down list to select the desired voice.
npm install react-native-dropdown-select-list --save
Using the react-native-tts library
First, we import the TextToSpeech library and the
import Tts from 'react-native-tts'
import { SelectList } from 'react-native-dropdown-select-list'
In a functional component, we add the states we’re interested in:
- selected voice
- selected gear
- voting list
- gear list
There are other parameters that could be interesting to test
- defaultLanguage
- defaultPitch defines the pitch of the voice (high or low)
- defaultRate defines voice playback speed
In a useEffect hook, we initialise the voice and gear lists and then assign the voice and gear selected by default.
N.B.: We use the promise resulting from the initialization of the TextToSpeech engine to ensure that it will be available when the component is initialized (Tts.getInitStatus().then(() => {)
useEffect(() => {
//console.log("init availableVoice",availableVoice)
if(availableVoice.length === 0){
console.log("No data found")
Tts.getInitStatus().then(() => {
Tts.voices().then(voices => {
voicesList = voices.map((voice,index) => {
//console.log(voice);
return {key: index, value: voice.name+"("+voice.language+")", disabled: voice.notInstalled==true ? true:false}
}) ;
langList = voices.map((voice,index) => {
return {key: index, value: voice.language, disabled: voice.notInstalled==true ? true:false}
}) ;
//console.log("voicesList", voicesList)
setAvailableVoice(voicesList);
}, (err) => {console.log("no voice loaded")}); //see all supported voices
Tts.engines().then(engines => {
engList = engines.map((engine,index) => {
return {key: index, value: engine.name}
});
//console.log("engList", engList)
setAvailableEng(engList);
}); //see all supported voices
}, (err) => {
console.log("TTS not loaded");
if (err.code === 'no_engine') {
Tts.requestInstallEngine();
}
});
}
if(voice !== ""){
Tts.setDefaultVoice(voice);
}
if(lang !== ""){
Tts.setDefaultLanguage(lang);
}
}, [availableVoice,availableEng, voice,lang, eng]);
Finally, we return the rendering, which includes the order:
- the drop-down list of available voices
- the drop-down list of available gears
- a text zone for writing the text to be read
- a button to read the text
return (
<View style={{ flexGrow: 1, flex: 1 }}>
<Text style={styles.mainTitle}>AC Text to Speech</Text>
<View style={styles.inputBar}>
<SelectList
setSelected={(val: React.SetStateAction<string>) => setVoice(val)}
data={availableVoice}
save="value"
/>
</View>
{/*} <View style={styles.inputBar}>
<SelectList
setSelected={(val: React.SetStateAction<string>) => setLang(val)}
data={availableLang}
save="value"
/>
</View>*/}
<View style={styles.inputBar}>
<SelectList
setSelected={(val: React.SetStateAction<string>) => setEng(val)}
data={availableEng}
save="value"
/>
</View>
<View
style={styles.inputBar}>
<TextInput
style={styles.textInput}
placeholder="Enter a message"
value={msgText}
onChangeText={(text) => setMsgText(text)
}
/>
<TouchableOpacity
onPress={() => Tts.speak(msgText, {
androidParams: {
KEY_PARAM_PAN: -1,
KEY_PARAM_VOLUME: 0.5,
KEY_PARAM_STREAM: 'STREAM_MUSIC',
},
})
}
style={[styles.sendButton]}>
<Text
style={styles.buttonText}>
Speak
</Text>
</TouchableOpacity>
</View>
{/*<Text>{currentDate}</Text>*/}
<View style={{flex: 1 }}>
</View>
</View>
)
Results
Once your code has been compiled and installed on your device, you can select and test the available voices (uninstalled voices are grayed out). Enter a text and press the “Speak” button to make your application speak.
Full source code: Text To Speech
/**
* npm install react-native-tts --save
* https://www.netguru.com/blog/react-native-text-to-speech
* https://www.npmjs.com/package/react-native-tts
*
* npm install react-native-dropdown-select-list --save
*/
import React, { useEffect, useState } from 'react'
import { Text, View, StyleSheet, TextInput, TouchableOpacity } from 'react-native'
import Tts from 'react-native-tts'
import { SelectList } from 'react-native-dropdown-select-list'
//Tts.setDefaultLanguage('en-GB')
Tts.setDefaultLanguage('fr-FR')
//Tts.setDefaultVoice('com.apple.ttsbundle.Daniel-compact')
//Tts.setDefaultRate(0.6);
//Tts.setDefaultPitch(1.5);
//Tts.setDefaultEngine('engineName');
//request install. app need reinstall after
let voicesList: { key: number; value: string; disabled: boolean }[] | ((prevState: never[]) => never[])= []
let langList = []
let engList: { key: number; value: string }[] | ((prevState: never[]) => never[]) = []
const App = () => {
const [msgText, setMsgText] = useState("");
const [voice, setVoice] = useState("")
const [lang, setLang] = useState("")
const [eng, setEng] = useState("")
const [availableVoice, setAvailableVoice] = useState([])
const [availableLang, setAvailableLang] = useState([])
const [availableEng, setAvailableEng] = useState([])
useEffect(() => {
//console.log("init availableVoice",availableVoice)
if(availableVoice.length === 0){
console.log("No data found")
Tts.getInitStatus().then(() => {
Tts.voices().then(voices => {
voicesList = voices.map((voice,index) => {
//console.log(voice);
return {key: index, value: voice.name+"("+voice.language+")", disabled: voice.notInstalled==true ? true:false}
}) ;
langList = voices.map((voice,index) => {
return {key: index, value: voice.language, disabled: voice.notInstalled==true ? true:false}
}) ;
//console.log("voicesList", voicesList)
setAvailableVoice(voicesList);
}, (err) => {console.log("no voice loaded")}); //see all supported voices
Tts.engines().then(engines => {
engList = engines.map((engine,index) => {
return {key: index, value: engine.name}
});
//console.log("engList", engList)
setAvailableEng(engList);
}); //see all supported voices
}, (err) => {
console.log("TTS not loaded");
if (err.code === 'no_engine') {
Tts.requestInstallEngine();
}
});
}
if(voice !== ""){
Tts.setDefaultVoice(voice);
}
if(lang !== ""){
Tts.setDefaultLanguage(lang);
}
}, [availableVoice,availableEng, voice,lang, eng]);
return (
<View style={{ flexGrow: 1, flex: 1 }}>
<Text style={styles.mainTitle}>AC Text to Speech</Text>
<View style={styles.inputBar}>
<SelectList
setSelected={(val: React.SetStateAction<string>) => setVoice(val)}
data={availableVoice}
save="value"
/>
</View>
{/*} <View style={styles.inputBar}>
<SelectList
setSelected={(val: React.SetStateAction<string>) => setLang(val)}
data={availableLang}
save="value"
/>
</View>*/}
<View style={styles.inputBar}>
<SelectList
setSelected={(val: React.SetStateAction<string>) => setEng(val)}
data={availableEng}
save="value"
/>
</View>
<View
style={styles.inputBar}>
<TextInput
style={styles.textInput}
placeholder="Enter a message"
value={msgText}
onChangeText={(text) => setMsgText(text)
}
/>
<TouchableOpacity
onPress={() => Tts.speak(msgText, {
androidParams: {
KEY_PARAM_PAN: -1,
KEY_PARAM_VOLUME: 0.5,
KEY_PARAM_STREAM: 'STREAM_MUSIC',
},
})
}
style={[styles.sendButton]}>
<Text
style={styles.buttonText}>
Speak
</Text>
</TouchableOpacity>
</View>
{/*<Text>{currentDate}</Text>*/}
<View style={{flex: 1 }}>
</View>
</View>
)
}
export default App;
let BACKGROUND_COLOR = "#161616"; //191A19
let BUTTON_COLOR = "#346751"; //1E5128
let ERROR_COLOR = "#C84B31"; //4E9F3D
let TEXT_COLOR = "#ECDBBA"; //D8E9A8
var styles = StyleSheet.create({
mainTitle:{
color: TEXT_COLOR,
fontSize: 30,
textAlign: 'center',
borderBottomWidth: 2,
borderBottomColor: ERROR_COLOR,
},
backgroundVideo: {
borderWidth: 2,
borderColor: 'red',
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0,
},
webVideo: {
borderWidth: 2,
borderColor: 'green',
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0,
},
buttonText: {
color: TEXT_COLOR,
fontWeight: 'bold',
fontSize: 12,
textAlign: 'center',
textAlignVertical: 'center',
},
sendButton: {
backgroundColor: BUTTON_COLOR,
padding: 15,
borderRadius: 15,
margin: 2,
paddingHorizontal: 20,
},
inputBar:{
flexDirection: 'row',
justifyContent: 'space-between',
margin: 5,
},
textInput:{
backgroundColor: '#888888',
margin: 2,
borderRadius: 15,
flex:3,
},
});
Applications
- Make your Android system talk, whether it’s a phone, a car or a robot!

