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?
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.
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);
}
}
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).
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é.
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.
divisez la messages
en parties et écoutez la dernière utterance
en utilisant onutteranceprogress
auditeur
tts.playSilence(1250, TextToSpeech.QUEUE_ADD, null);
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.
J'ai utilisé une approche différente.
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()
}
}
}
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.
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");
}
}