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

Я играю в текст с Android TTS - android.speech.tts.TextToSpeech

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


person Jas    schedule 11.02.2011    source источник


Ответы (10)


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

person Aaron C    schedule 12.02.2011
comment
Пожалуйста, дайте мне знать, как мы можем узнать, когда поставить медиаплеер на паузу? Например: если в строке есть пауза после 50 символов, как мы узнаем, в какой позиции нам нужно приостановить медиаплеер? - person AndroidDev; 06.12.2013

Я использовал разбиение строки и использовал playsilence(), как показано ниже:

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);
    }
}
person rushi    schedule 22.05.2013
comment
большое спасибо .. Это работает для меня .. но я столкнулся с проблемой, что он оставляет слово, которое я передаю в speech.split(xyz). Например, у меня есть предложение как Android и Java, а затем speech.split (и), затем сначала воспроизводится Android, затем приостанавливается на заданное время, а затем воспроизводится Java. Его уход и без игры - person N.R; 22.01.2018
comment
Разделить по пространству, т.е. speech.split(\\s+) - person rushi; 30.01.2018
comment
добавьте \n в строку, где вы хотите сделать паузу - person Qamar; 28.02.2019

Вы можете сделать паузу в 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();
                    }
                }
            }

        }
    }
};

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

person jroal    schedule 14.08.2011
comment
это зависит от разных TTS - person djdance; 29.07.2017

При отсутствии опции паузы вы можете добавить тишину на время, когда вы хотите отложить речь механизма TTS. Это, конечно, должна быть предопределенная «пауза» и, например, не поможет включить функциональность кнопки паузы.

Для 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, иначе он очистит ранее начатую речь.

person brandall    schedule 11.05.2012

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

  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()
        }
    }
}
person rm -rf    schedule 12.12.2018

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

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

person SiteKickr    schedule 14.08.2012

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

 tts.playSilence(1250, TextToSpeech.QUEUE_ADD, null);
person Dev    schedule 19.09.2014

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

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

тогда в «доме. Мы» будет пауза.

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

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

person user655489    schedule 05.09.2011

Это решение не идеально, но альтернативой решению @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");
    }
}
person gareoke    schedule 31.08.2017
comment
где ссылка на ттс? - person MrCurious; 14.03.2019
comment
Что такое TTS_INTERVAL_MS и TTS_SETUP_TIME_MS? - person MrCurious; 14.03.2019
comment
TTS_INTERVAL_MS будет повторять произносимый текст в этом заданном интервале. Вы можете изменить на .post вместо .postDelayed, если это нежелательно (просто помогает при тестировании паузы и возобновления с вашим текстом). TTS_SETUP_TIME_MS — это время задержки, которое вы хотите подождать, пока текст не будет произнесен. - person gareoke; 14.03.2019