web-dev-qa-db-fra.com

Comment mettre en pause Android.speech.tts.TextToSpeech?

Je joue un texte avec Android TTS - Android.speech.tts.TextToSpeech

J'utilise: TextToSpeech.speak pour parler et .stop pour arrêter. Est-il possible de mettre le texte en pause également?

20
Jas

Le Kit de développement logiciel (SDK) TTS ne possède aucune fonctionnalité de pause à ma connaissance. Mais vous pouvez utiliser synthesizeToFile() pour créer un fichier audio contenant la sortie TTS. Ensuite, vous utiliseriez un objet MediaPlayer pour lire, mettre en pause et arrêter la lecture du fichier. En fonction de la longueur de la chaîne de texte, la production de l'audio peut prendre un peu plus longtemps car la fonction synthesizeToFile() doit terminer la totalité du fichier avant de pouvoir être lue, mais ce délai devrait être acceptable pour la plupart des applications.

23
Aaron C

J'ai utilisé le dédoublement de chaîne et ai utilisé playsilence () comme ci-dessous:

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);
    }
}
13
rushi

Vous pouvez faire une pause de la synthèse vocale entre les phrases ou n'importe où en ajoutant jusqu'à trois points (".") Suivis d'un seul espace "". L'exemple ci-dessous comporte une longue pause au début, puis de nouveau avant le corps du message. Je ne suis pas sûr que ce soit ce que vous recherchez.

    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 vous omettez l'espace après la dernière période, cela ne fonctionnera pas (ou risque de ne pas l'être).

6
jroal

En l'absence d'une option de pause, vous pouvez ajouter du silence pendant toute la durée pendant laquelle vous souhaitez retarder la prise de parole du moteur TTS. Bien sûr, cela devrait être une "pause" prédéterminée et ne contribuerait en rien à inclure la fonctionnalité d'un bouton de pause, par exemple.

Pour API <21: public int playSilence (paramètres d'instance longue durée, int queueMode, HashMap)

Pour> 21: public int playSilentUtterance (long durationInMs, int queueMode, String utteranceId)

N'oubliez pas d'utiliser TextToSpeech.QUEUE_ADD plutôt que TextToSpeech.QUEUE_FLUSH sinon, le discours précédemment lancé sera effacé.

4
brandall

Je n'ai pas encore essayé cela, mais je dois faire la même chose. Ma pensée est d’abord de scinder votre texte de discours en un ensemble de mots.

Créez ensuite une fonction récursive qui lit le prochain mot une fois le mot actuel terminé, tout en conservant un compteur du mot actuel.

3
SiteKickr

divisez la messages en parties et écoutez la dernière utterance en utilisant onutteranceprogress auditeur

 tts.playSilence(1250, TextToSpeech.QUEUE_ADD, null);
2
Dev

Il semble que si vous mettez un point après un mot et que vous commencez le mot suivant avec une majuscule, comme une nouvelle phrase, comme ceci:

après notre retour à la maison. Nous avons mangé le souper.

la "maison. Nous" aurons alors une pause en elle.

  • Cela devient une manière grammaticalement étrange de l'écrire.
  • Jusqu'à présent, je n'ai testé cela que dans ma propre langue, le suédois.
  • Il pourrait être important que l'espace soit là.
2
Magnus

J'ai utilisé une approche différente.

  1. Séparez votre texte en phrases
  2. Prononcez chaque phrase une à une et gardez une trace de la phrase parlée
  3. pause arrêtera le texte instantanément
  4. le CV commencera au début de la dernière phrase parlée

Code 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()
        }
    }
}
0
rm -rf

De plus, une citation échappée ("") semble également avoir une pause - du moins, si vous la mettez autour d'un mot, elle ajoute de l'espace autour de la parole.

0
user655489

Cette solution n'est pas parfaite, mais une alternative à la solution de @Aaron C pourrait être de créer une classe de synthèse vocale personnalisée comme ci-dessous. Cette solution peut fonctionner assez bien si votre texte est relativement court et si le nombre de mots parlés à la minute est suffisamment précis pour la langue que vous utilisez.

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");
    }
}
0
gareoke