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ô!