Текст в речь не воспроизводит звук в первый раз, но играет в следующий раз
Я использую этот тип текста для речи в одном из моих классов в моем приложении (код отредактирован, чтобы показать внешний вид и точное требование.). Я покажу контент на мой взгляд, и если мы нажмем кнопку, я хочу воспроизвести звук, используя этот тексто-речевой движок... Но впервые он не воспроизводит звук. После следующего нажатия, двигатель 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 Text-To-Speech...
3 ответа
Это потому, что вы нажимаете кнопку до того, как двигатель будет готов.
Вы должны проверить, успешно ли инициализирован двигатель TTS на вашем onInit()
метод и включить / отключить кнопку воспроизведения соответственно.
При условии, что bt
в твоем коде какая то View
который имеет setEnabled(boolean)
метод:
@Override
public void onInit(int status) {
bt.setEnabled(status == TextToSpeech.SUCCESS);
}
Вы всегда должны предполагать, что двигатель не был инициализирован, и, следовательно, по умолчанию кнопка воспроизведения отключена.
Я использовал RXJava, чтобы создать класс, решающий эту проблему. Если ваш движок TTS не готов, когда вы хотите использовать метод Speech, он будет ждать, пока движок подготовится, а затем произносит заданную строку.
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();
}
}
сначала добавьте зависимость RxJava в свой файл Gradle
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
Затем создайте экземпляр этого класса в методе onCreate вашей активности или фрагмента. Теперь вы можете передать строку и режим очереди методу Speak.
pronunciation.speak("Hi", TextToSpeech.QUEUE_FLUSH));
Не забудьте вызвать метод остановки в onDestroy или onDetach, чтобы избежать утечки памяти.
@Override
public void onDetach() {
super.onDetach();
pronunciation.stop();
}
Вы должны написать свою программу...
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);
Просто установите задержку на 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);
}
}
}