fbpixel
Etiquetas: , ,

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.

android-app-react-native-tts Dale voz a tu dispositivo Android con React Native TTS

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!

Fuentes