Я играю в текст с Android TTS - android.speech.tts.TextToSpeech
Я использую: TextToSpeech.speak
, чтобы говорить, и .stop
, чтобы остановиться. Есть ли способ приостановить текст?
Я играю в текст с Android TTS - android.speech.tts.TextToSpeech
Я использую: TextToSpeech.speak
, чтобы говорить, и .stop
, чтобы остановиться. Есть ли способ приостановить текст?
Насколько мне известно, в TTS SDK нет функций паузы. Но вы можете использовать synthesizeToFile()
, чтобы создать аудиофайл, содержащий вывод TTS. Затем вы должны использовать объект MediaPlayer для воспроизведения, приостановки и остановки. воспроизведение файла. В зависимости от длины текстовой строки для воспроизведения звука может потребоваться немного больше времени, потому что функция synthesizeToFile()
должна будет завершить весь файл, прежде чем вы сможете его воспроизвести, но эта задержка должна быть приемлемой для большинства приложений.
Я использовал разбиение строки и использовал 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);
}
}
Вы можете сделать паузу в 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();
}
}
}
}
}
};
Если вы опустите пробел после последней точки, он будет (или может) работать не так, как ожидалось.
При отсутствии опции паузы вы можете добавить тишину на время, когда вы хотите отложить речь механизма 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, иначе он очистит ранее начатую речь.
Я использовал другой подход.
Код Котлина:
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()
}
}
}
Я еще не пробовал это, но мне нужно сделать то же самое. Я думаю, сначала разбить ваш речевой текст на массив слов.
Затем создайте рекурсивную функцию, которая воспроизводит следующее слово после завершения текущего слова, сохраняя при этом счетчик текущего слова.
разделите messages
на части и прослушайте последние utterance
с помощью прослушивателя onutteranceprogress
tts.playSilence(1250, TextToSpeech.QUEUE_ADD, null);
Кажется, что если поставить точку после слова И начать следующее слово с заглавной буквы, как новое предложение, вот так:
после того, как мы вернулись домой. Мы поужинали.
тогда в «доме. Мы» будет пауза.
Кроме того, экранированная кавычка (\"), по-видимому, также делает паузу - по крайней мере, если вы поместите ее вокруг слова, она добавит пробел вокруг слова.
Это решение не идеально, но альтернативой решению @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");
}
}