Neste tutorial, vamos ver como dar uma voz ao seu dispositivo Android utilizando uma biblioteca Text to Speech (TTS). Quer esteja a desenvolver aplicações para pessoas com deficiência visual ou a tentar animar o seu sistema Android, dar uma voz ao seu projeto pode ser uma funcionalidade interessante. Para isso, vamos integrar a biblioteca react-native-tts numa aplicação Android desenvolvida com React Native.
Hardware
- Dispositivo Android
- Computador para programação
- Um cabo USB para ligar o dispositivo Android ao PC
Configurar o projeto React Native
A biblioteca de conversão de texto em fala react-native-tts permite-lhe utilizar as vozes, ou modelos de conversão de texto em fala, disponíveis no seu dispositivo Android para ler texto.
npm install react-native-tts --save
Utilizamos uma lista pendente para selecionar a voz pretendida.
npm install react-native-dropdown-select-list --save
Utilizar a biblioteca react-native-tts
Em primeiro lugar, importamos a biblioteca TextToSpeech para o código, juntamente com a lista pendente
import Tts from 'react-native-tts'
import { SelectList } from 'react-native-dropdown-select-list'
Numa componente funcional, adicionamos os estados que nos interessam:
- voz selecionada
- mudança selecionada
- lista de votação
- lista de equipamentos
Há outros parâmetros que podem valer a pena testar
- defaultLanguage
- defaultPitch define o tom da voz (alto ou baixo)
- defaultRate define a velocidade de reprodução de voz
Num gancho useEffect, inicializamos as listas de vozes e equipamentos e, em seguida, atribuímos a voz e o equipamento seleccionados por defeito.
Nota: Utilizamos a promessa resultante da inicialização do motor TextToSpeech para garantir que está disponível quando o componente é inicializado (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 fim, devolvemos a renderização, que é incluída na encomenda:
- a lista pendente de vozes disponíveis
- a lista pendente de equipamentos disponíveis
- uma caixa de texto para escrever o texto a ser lido
- um botão para ler o 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
Depois de o código ter sido compilado e instalado no seu dispositivo, pode selecionar e testar as vozes disponíveis (as vozes não instaladas estão a cinzento). Introduza um texto e prima o botão “Falar” para fazer a sua aplicação falar.
Código fonte 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,
},
});
Aplicações
- Faça o seu sistema Android falar, quer se trate de um telefone, de um carro ou de um robô!

