Подтвердить что ты не робот

Как приостановить android.speech.tts.TextToSpeech?

Я играю текст с андроидом TTS - android.speech.tts.TextToSpeech

Я использую: TextToSpeech.speak, чтобы говорить, и .stop для остановки. Есть ли способ также приостановить текст?

4b9b3361

Ответ 1

У TTS SDK нет никаких функций паузы, о которых я знаю. Но вы можете использовать synthesizeToFile() для создания аудиофайла, содержащего вывод TTS. Затем вы будете использовать объект MediaPlayer для воспроизведения, приостановки и остановки воспроизведения файла. В зависимости от длины текстовой строки может потребоваться немного больше времени для создания звука, потому что функция synthesizeToFile() должна была бы завершить весь файл, прежде чем вы сможете его воспроизвести, но эта задержка должна быть приемлемой для большинства приложений.

Ответ 2

Я использовал расщепление строки и используемую функцию playilence(), как показано ниже:

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

Ответ 3

Вы можете сделать паузу TTS между предложениями или в любом месте, добавив до трех периодов ( "." ), за которыми следует одно место "". Пример ниже имеет длительную паузу в начале и снова перед телом сообщения. Я не уверен, что это то, что вам нужно.

    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();
                    }
                }
            }

        }
    }
};

Если вы опустите пробел после последнего периода, он будет (или может) работать не так, как ожидалось.

Ответ 4

В случае отсутствия опции паузы вы можете добавить молчание в течение продолжительности, когда вы хотите задержать работу TTS Engine. Это, конечно, должно быть предопределенной "паузой" и, например, не включало бы функциональность кнопки паузы.

Для API < 21: public int playSilence (long durationInMs, int queueMode, параметры HashMap)

Для > 21: public int playSilentUtterance (long durationInMs, int queueMode, String utteranceId)

Не забудьте использовать TextToSpeech.QUEUE_ADD, а не TextToSpeech.QUEUE_FLUSH в противном случае он очистит ранее запущенную речь.

Ответ 5

Я еще этого не пробовал, но мне нужно сделать то же самое. Мое мышление состоит в том, чтобы сначала разделить текст речи на несколько слов.

Затем создайте рекурсивную функцию, которая воспроизводит следующее слово после завершения текущего слова, сохраняя при этом счетчик текущего слова.

Ответ 6

разделите messages на части и прослушайте последние utterance, используя onutteranceprogress прослушиватель

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

Ответ 7

Кажется, что если вы поместите период после слова И начните следующее слово с большой буквы, как новое предложение, например:

после того, как мы вернулись домой. Мы обедали.

"дом. У нас" будет пауза.

  • Это становится грамматически странным способом его написания.
  • Пока я тестировал это только на своем родном языке, шведский.
  • Может быть, важно, чтобы пространство было.

Ответ 8

Кроме того, у экранированной цитаты (\) кажется, что она несколько приостанавливается - по крайней мере, если вы поместили ее вокруг слова, она добавит пространство вокруг слова.

Ответ 9

Это решение не идеально, но альтернативой решению @Aaron C может быть создание пользовательского текста в речь, как показано ниже. Это решение может работать достаточно хорошо, если ваш текст относительно короткий и произнесенные слова в минуту достаточно точны для используемого вами языка.

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

Ответ 10

Я использовал другой подход.

  1. Разделите ваш текст на предложения
  2. Произнесите каждое предложение одно за другим и отслеживайте произнесенное предложение.
  3. пауза остановит текст мгновенно
  4. резюме начнется в начале последнего произнесенного предложения

Код Котлина:

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()
        }
    }
}