studio - text to speech android español
¿Cómo pausar android.speech.tts.TextToSpeech? (10)
Estoy reproduciendo texto con TTS de Android - android.speech.tts.TextToSpeech
Yo uso: TextToSpeech.speak
para hablar y .stop
para detener. ¿Hay alguna forma de pausar el texto también?
Además, una cita escapada (/ ") parece hacer que se detenga un poco también, al menos, si la pones alrededor de una palabra, agrega espacio alrededor de la palabra.
El SDK de TTS no tiene ninguna funcionalidad de pausa que yo sepa. Pero puede usar synthesizeToFile()
para crear un archivo de audio que contenga la salida TTS. Luego, usaría un objeto MediaPlayer para reproducir, pausar y detener la reproducción del archivo. Dependiendo de la longitud de la cadena de texto, el audio puede tardar un poco más en producirse porque la función synthesizeToFile()
tendría que completar todo el archivo antes de poder reproducirlo, pero este retraso debería ser aceptable para la mayoría de las aplicaciones.
En ausencia de una opción de pausa, puede agregar silencio durante el tiempo en que desee retrasar el habla del motor TTS. Por supuesto, esto tendría que ser una "pausa" predeterminada y no ayudaría a incluir la funcionalidad de un botón de pausa, por ejemplo.
Para API <21: public int playSilence (long durationInMs, int queueMode, HashMap params)
Para> 21: public int playSilentUtterance (long durationInMs, int queueMode, String utteranceId)
Recuerde utilizar TextToSpeech.QUEUE_ADD lugar de TextToSpeech.QUEUE_FLUSH contrario se borrará la voz iniciada anteriormente.
Esta solución no es perfecta, pero una alternativa a la solución de @Aaron C puede ser crear una clase personalizada de texto a voz como la que se muestra a continuación. Esta solución puede funcionar lo suficientemente bien si su texto es relativamente corto y las palabras habladas por minuto son lo suficientemente precisas para el idioma que está utilizando.
private class CustomTextToSpeech extends TextToSpeech {
private static final double WORDS_PER_MS = (double)190/60/1000;
long startTimestamp = 0;
long pauseTimestamp = 0;
private Handler handler;
private Runnable speakRunnable;
StringBuilder textToSpeechBuilder;
private boolean isPaused = false;
public CustomTextToSpeech(Context context, OnInitListener initListener){
super(context, initListener);
setOnUtteranceProgressListener(new UtteranceProgressListener() {
@Override
public void onDone(String arg0) {
Log.d(TAG, "tts done. " + arg0);
startTimestamp = 0;
pauseTimestamp = 0;
handler.postDelayed(speakRunnable, TTS_INTERVAL_MS);
}
@Override
public void onError(String arg0) {
Log.e(TAG, "tts error. " + arg0);
}
@Override
public void onStart(String arg0) {
Log.d(TAG, "tts start. " + arg0);
setStartTimestamp(System.currentTimeMillis());
}
});
handler = new Handler();
speakRunnable = new Runnable() {
@Override
public void run() {
speak();
}
};
textToSpeechBuilder = new StringBuilder(getResources().getString(R.string.talkback_tips));
}
public void setStartTimestamp(long timestamp) {
startTimestamp = timestamp;
}
public void setPauseTimestamp(long timestamp) {
pauseTimestamp = timestamp;
}
public boolean isPaused(){
return (startTimestamp > 0 && pauseTimestamp > 0);
}
public void resume(){
if(handler != null && isPaused){
if(startTimestamp > 0 && pauseTimestamp > 0){
handler.postDelayed(speakRunnable, TTS_SETUP_TIME_MS);
} else {
handler.postDelayed(speakRunnable, TTS_INTERVAL_MS);
}
}
isPaused = false;
}
public void pause(){
isPaused = true;
if (handler != null) {
handler.removeCallbacks(speakRunnable);
handler.removeMessages(1);
}
if(isSpeaking()){
setPauseTimestamp(System.currentTimeMillis());
}
stop();
}
public void utter(){
if(handler != null){
handler.postDelayed(speakRunnable, TTS_INTERVAL_MS);
}
}
public void speak(){
Log.d(TAG, "textToSpeechBuilder: " + textToSpeechBuilder.toString());
if(isPaused()){
String[] words = textToSpeechBuilder.toString().split(" ");
int wordsAlreadySpoken = (int)Math.round((pauseTimestamp - startTimestamp)*WORDS_PER_MS);
words = Arrays.copyOfRange(words, wordsAlreadySpoken-1, words.length);
textToSpeechBuilder = new StringBuilder();
for(String s : words){
textToSpeechBuilder.append(s);
textToSpeechBuilder.append(" ");
}
} else {
textToSpeechBuilder = new StringBuilder(getResources().getString(R.string.talkback_tips));
}
if (tts != null && languageAvailable)
speak(textToSpeechBuilder.toString(), TextToSpeech.QUEUE_FLUSH, new Bundle(), "utter");
}
}
Parece que si pone un punto después de una palabra Y comienza la siguiente palabra con una letra mayúscula, al igual que una nueva oración, como esta:
después de que llegamos a casa. Comimos la cena.
el "hogar. Nosotros" entonces tendremos una pausa en él.
- Esto se convierte en una forma gramaticalmente extraña de escribirlo.
- Hasta ahora solo he probado esto en mi propio idioma, el sueco.
- Puede ser importante que el espacio esté ahí.
Puede hacer que el TTS se detenga entre oraciones, o en cualquier lugar que desee, agregando hasta tres puntos ("."), Todos seguidos de un solo espacio "". El siguiente ejemplo tiene una larga pausa al principio, y nuevamente antes del cuerpo del mensaje. Aunque no estoy seguro de que es lo que buscas.
private final BroadcastReceiver SMScatcher = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
if (intent.getAction().equals(
"android.provider.Telephony.SMS_RECEIVED")) {
// if(message starts with SMStretcher recognize BYTE)
StringBuilder sb = new StringBuilder();
/*
* The SMS-Messages are ''hiding'' within the extras of the
* Intent.
*/
Bundle bundle = intent.getExtras();
if (bundle != null) {
/* Get all messages contained in the Intent */
Object[] pdusObj = (Object[]) bundle.get("pdus");
SmsMessage[] messages = new SmsMessage[pdusObj.length];
for (int i = 0; i < pdusObj.length; i++) {
messages[i] = SmsMessage
.createFromPdu((byte[]) pdusObj[i]);
}
/* Feed the StringBuilder with all Messages found. */
for (SmsMessage currentMessage : messages) {
// periods are to pause
sb.append("... Message From: ");
/* Sender-Number */
sb.append(currentMessage.getDisplayOriginatingAddress());
sb.append(".. ");
/* Actual Message-Content */
sb.append(currentMessage.getDisplayMessageBody());
}
// Toast.makeText(application, sb.toString(),
// Toast.LENGTH_LONG).show();
if (mTtsReady) {
try {
mTts.speak(sb.toString(), TextToSpeech.QUEUE_ADD,
null);
} catch (Exception e) {
Toast.makeText(application, "TTS Not ready",
Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
}
}
}
};
Si omite el espacio después del último período, (o puede que) no funcione como se esperaba.
Todavía no he intentado esto, pero necesito hacer lo mismo. Mi pensamiento es dividir primero el texto de tu discurso en una serie de palabras.
Luego cree una función recursiva que reproduzca la siguiente palabra después de que la palabra actual haya terminado, mientras mantiene un contador de la palabra actual.
Usé la división de cuerdas y usé playsilence () como a continuación:
public void speakSpeech(String speech) {
HashMap<String, String> myHash = new HashMap<String, String>();
myHash.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "done");
String[] splitspeech = speech.split("//.");
for (int i = 0; i < splitspeech.length; i++) {
if (i == 0) { // Use for the first splited text to flush on audio stream
textToSpeech.speak(splitspeech[i].toString().trim(),TextToSpeech.QUEUE_FLUSH, myHash);
} else { // add the new test on previous then play the TTS
textToSpeech.speak(splitspeech[i].toString().trim(), TextToSpeech.QUEUE_ADD,myHash);
}
textToSpeech.playSilence(750, TextToSpeech.QUEUE_ADD, null);
}
}
Utilicé un enfoque diferente.
- Separa tu texto en oraciones
- Pronuncie cada oración una por una y haga un seguimiento de la oración hablada
- pausa detendrá el texto al instante
- el currículum comenzará al principio de la última oración hablada
Código Kotlin:
class VoiceService {
private lateinit var textToSpeech: TextToSpeech
var sentenceCounter: Int = 0
var myList: List<String> = ArrayList()
fun resume() {
sentenceCounter -= 1
speakText()
}
fun pause() {
textToSpeech.stop()
}
fun stop() {
sentenceCounter = 0
textToSpeech.stop()
}
fun speakText() {
var myText = "This is some text to speak. This is more text to speak."
myList =myText.split(".")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
textToSpeech.speak(myList[sentenceCounter], TextToSpeech.QUEUE_FLUSH, null, utteranceId)
sentenceCounter++
} else {
var map: HashMap<String, String> = LinkedHashMap<String, String>()
map[TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID] = utteranceId
textToSpeech.speak(myList[sentenceCounter], TextToSpeech.QUEUE_FLUSH, map)
sentenceCounter++
}
}
override fun onDone(p0: String?) {
if (sentenceCounter < myList.size) {
speakText()
} else {
speakNextText()
}
}
}
divida los messages
en partes y escuche la última utterance
usando el oyente onutteranceprogress
tts.playSilence(1250, TextToSpeech.QUEUE_ADD, null);