En este tutorial veremos cómo dar voz a tu dispositivo Android utilizando una librería de Texto a Voz (TTS). Tanto si estás desarrollando aplicaciones para discapacitados visuales como si buscas darle vida a tu sistema Android, dotar de voz a tu proyecto puede ser una función interesante. Para ello, vamos a integrar la librería react-native-tts en una aplicación Android desarrollada con React Native.
Hardware
- Dispositivo Android
- Ordenador para programar
- Un cable USB para conectar el dispositivo Android al PC
Configuración del proyecto React Native
La biblioteca de texto a voz react-native-tts te permite utilizar las voces, o modelos de texto a voz, disponibles en tu dispositivo Android para leer texto.
npm install react-native-tts --save
Utilizamos una lista desplegable para seleccionar la voz que desee.
npm install react-native-dropdown-select-list --save
Uso de la biblioteca react-native-tts
En primer lugar, importamos la biblioteca TextToSpeech en el código, junto con la lista desplegable
import Tts from 'react-native-tts'
import { SelectList } from 'react-native-dropdown-select-list'
En un componente funcional, añadimos los estados que nos interesan:
- voz seleccionada
- marcha seleccionada
- lista de votación
- lista de equipos
Hay otros parámetros que podría valer la pena probar
- defaultLanguage
- defaultPitch define el tono de la voz (alto o bajo)
- defaultRate establece la velocidad de reproducción de la voz
En un hook useEffect, inicializamos las listas de voces y marchas y luego asignamos la voz y la marcha seleccionadas por defecto.
N.B.: Utilizamos la promesa resultante de la inicialización del motor TextToSpeech para asegurarnos de que está disponible cuando se inicializa el componente (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]);
Por último, devolvemos el renderizado, que se incluye en el pedido:
- la lista desplegable de voces disponibles
- la lista desplegable de marchas disponibles
- un cuadro de texto para escribir el texto que se va a leer
- un botón para leer el texto
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>
)
Resultados
Una vez que tu código haya sido compilado e instalado en tu dispositivo, puedes seleccionar y probar las voces disponibles (las voces no instaladas aparecen atenuadas). Introduce un texto y pulsa el botón «Hablar» para que tu aplicación hable.

Código fuente completo: 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,
},
});
Aplicaciones
- Haz que tu sistema Android hable, ¡ya sea un teléfono, un coche o un robot!