文本到语音不是第一次播放声音,而是下次播放

时间:2013-06-04 12:44:31

标签: android text-to-speech

我在我的应用程序中使用此类文本进行演讲(代码编辑以显示前景和确切要求。)。我将在我的观点和展示中展示一些内容。如果我们点击按钮,我想通过使用这个texttospeech引擎播放声音...但是对于第一次它没有播放声音。从下一次点击开始,TEXTTOSPEECH引擎运行良好

我想知道如何克服这个问题......

public class LearnActivity extends Activity implements OnClickListener, OnInitListener {

AudioManager audioManager;
float volume;

TextToSpeech textToSpeech;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_learn);

   textToSpeech = new TextToSpeech(this, this);
    textToSpeech.setLanguage(Locale.US);
    textToSpeech.setSpeechRate(0.95f);

       method();
}
   public void method(){
      bt.setonClickListener(new onClickListener(){
        public void onClick(View v){
                        playSound(datasource.getItemSound);                  
              }

        });

      }
   public void playSound(String sound){
         textToSpeech.speak(sound,TextToSpeech.QUEUE_FLUSH,null);
         }   

@Override
public void onInit(int status) {
    // TODO Auto-generated method stub

}

注意: - 这也符合我的要求,如何直接播放TEXTTOSPEECH引擎的声音,而不使用任何onClicks等...,因为我也想用Android播放启动声音仅限文字转语音引擎......

4 个答案:

答案 0 :(得分:1)

那是因为你在引擎准备好之前点击了按钮。

您必须检查TTS引擎是否已在onInit()方法上成功初始化,并相应地启用/禁用播放按钮。

假设代码中的btView某种setEnabled(boolean)方法:

@Override
public void onInit(int status) {
    bt.setEnabled(status == TextToSpeech.SUCCESS);
}

您始终必须假设引擎尚未初始化,因此默认情况下会禁用播放按钮。

答案 1 :(得分:0)

我使用RXJava制作了一个解决此问题的类。如果要使用语音方法时TTS引擎尚未准备就绪,它将等待引擎准备就绪,然后说出给定的字符串。

import android.content.Context;
import android.speech.tts.TextToSpeech;
import android.util.Pair;
import android.widget.Toast;

import java.util.Locale;

import io.reactivex.Observable;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.PublishSubject;

public class Pronunciation {

    private TextToSpeech textToSpeech;
    private int languageResult;
    private boolean noError;
    private final String errorMessage="Something went wrong with your text to speech engine";
    private PublishSubject<Boolean> engineIsReady=PublishSubject.create();
    private PublishSubject<Pair<String,Integer>> speakObservable=PublishSubject.create();
    private CompositeDisposable compositeDisposable=new CompositeDisposable();

    public Pronunciation(Context context) {
        textToSpeech=new TextToSpeech(context, status -> {

            if (status!=TextToSpeech.ERROR){
               languageResult=  textToSpeech.setLanguage(Locale.ENGLISH);
               engineIsReady.onNext(true);
            } else {
                Toast.makeText(context,errorMessage
                        ,Toast.LENGTH_LONG).show();
            }

        });

        if (languageResult==TextToSpeech.LANG_MISSING_DATA||languageResult== TextToSpeech.LANG_NOT_SUPPORTED){
            noError =false;
            Toast.makeText(context,errorMessage
                    ,Toast.LENGTH_LONG).show();
        }else { noError =true;}


        compositeDisposable.add( Observable.combineLatest(speakObservable, engineIsReady,
                (stringIntegerPair, aBoolean) -> stringIntegerPair)
                .subscribeOn(Schedulers.io())
                .subscribe(pair->{

                    if (noError)
                        textToSpeech.speak( (pair).first
                                ,(pair).second,null,null);
                }));


    }


    public void speak(String text,int queueMode){

        speakObservable.onNext(new Pair<>(text,queueMode));

    }

    public void stop(){
        if (textToSpeech!=null){
            textToSpeech.stop();
            textToSpeech.shutdown();
        }
        compositeDisposable.clear();
    }
}

首先在您的Gradle文件中添加RxJava依赖项

implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'

然后在活动或片段的onCreate方法中创建此类的实例。现在,您可以将字符串和队列模式传递给语音方法。

pronunciation.speak("Hi", TextToSpeech.QUEUE_FLUSH));

不要忘记在onDestroy或onDetach中调用stop方法,以避免内存泄漏

@Override
public void onDetach() {
    super.onDetach();
    pronunciation.stop();
}

答案 2 :(得分:-1)

你应该写你的程序......

public class MainActivity extends Activity implements TextToSpeech.OnInitListener, OnUtteranceCompletedListener {

  TextToSpeech t1;

  protected void onCreate(Bundle savedInstanceState) {
    t1=new TextToSpeech(MainActivity.this, MainActivity.this);   
  }/////on creat

  protected void onDestroy() {
    if(t1!=null) {
      t1.stop();
      t1.shutdown();
      t1=null;
    }
    super.onDestroy();
  }

  public void onInit(int arg0) {
      t1.setOnUtteranceCompletedListener(this);
  }

}//mainactivity

单击按钮或在任何想要说文本的位置添加此命令。

t1.speak(text, TextToSpeech.QUEUE_FLUSH, null);

答案 3 :(得分:-2)

只需延迟5秒钟就可以在没有任何按钮的情况下工作点击

public class Final_Text_To_Speech_Activity extends AppCompatActivity implements TextToSpeech.OnInitListener {

private TextToSpeech tts; // For Text to Speech
CardView ScanProduct, SearchProduct;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    tts = new TextToSpeech(this, this);
    init();

    // Just Put Delay For 5 Second And It's Working without any button Click
    Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        public void run() {

            SpeakOutOnce("Welcome to Text To Speech Application");
        }
    }, 5000);


}


@Override
protected void onResume() {
    super.onResume();


}


public void init() {

    ScanProduct = (CardView) findViewById(R.id.scan_product);
    SearchProduct = (CardView) findViewById(R.id.search_product);


    // Search On Button Click
    ScanProduct.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            speakOut("You have Just pressed Scan  Option");
        }
    });


    SearchProduct.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            speakOut("You have Just pressed Search Option ");
        }
    });


}


@Override
public void onDestroy() {
    if (tts != null) {
        tts.stop();
        tts.shutdown();
    }
    super.onDestroy();
}


@Override
public void onInit(int status) {

    int result = tts.setLanguage(Locale.US);
    if (status == TextToSpeech.SUCCESS) {

        if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) {
        } else {
            speakOut("");
        }
    } else if (status == TextToSpeech.ERROR) {
        Toast.makeText(this, "Sorry! Text To Speech failed...",
                Toast.LENGTH_LONG).show();
    }
}


private void speakOut(String text) {

    tts.setPitch(1.0f); //Normal Pitch
    tts.setSpeechRate(0.7f); // 1.0 is Normal speech Rate
    tts.speak(text, TextToSpeech.QUEUE_FLUSH, null);

}


private void SpeakOutOnce(String text) {

    if (tts != null) {
        tts.setPitch(1.0f); //Normal Pitch
        tts.setSpeechRate(0.7f); // 1.0 is Normal speech Rate
        tts.speak(text, TextToSpeech.QUEUE_FLUSH, null);
    }
}

}