gpt4 book ai didi

android - 绕过 Android 中的 Google TTS 引擎初始化延迟

转载 作者:可可西里 更新时间:2023-11-01 18:47:00 26 4
gpt4 key购买 nike

我尝试在手机中触发特定事件时播放 TextToSpeech 对象。

但是,我遇到了大多数手机上安装的默认 Google TTS 引擎的问题。截至目前,我正在 TextToSpeech 对象初始化后立即播放一些文本,并在语音完成后立即关闭资源,按照以下代码:

public class VoiceGenerator {
private Context context = null;

private static TextToSpeech voice = null;

public VoiceGenerator(Context context)
{
this.context = context;
}


public void voiceInit(String text)
{
try {
if (voice == null) {

new Thread(new Runnable() {
@Override
public void run() {
voice = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
@Override
public void onInit(final int status) {
try {
if (status != TextToSpeech.ERROR) {
voice.setLanguage(Locale.US);
Log.d("VoiceTTS", "TTS being initialized");
HashMap p = new HashMap<String, String>();
p.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "ThisUtterance");

//Speaking here
voice.speak(text, TextToSpeech.QUEUE_ADD, p);

voice.setOnUtteranceProgressListener(new UtteranceProgressListener() {
@Override
public void onStart(String utteranceId) {

}

@Override
public void onDone(String utteranceId) {
Log.d("VoiceTTS", "TTS being released");
clearTtsEngine();
}

@Override
public void onError(String utteranceId) {

}
});
}

} catch (Exception e) {
clearTtsEngine();
Log.d("ErrorLog", "Error occurred while voice play");
e.printStackTrace();
}


}
});
}
}).start();

}
}
catch(Exception e)
{
clearTtsEngine();
Log.d("ErrorLog","Error occurred while voice play");
e.printStackTrace();
}
}

public static void clearTtsEngine()
{
if(voice!=null)
{
voice.stop();
voice.shutdown();
voice = null;
}



}
}

但是,我面临的问题是 与初始化 Google TTS 引擎相关的有限延迟 - 在我的设备上大约 6-8 秒 .

我在其他帖子中读到过使用其他 TTS 引擎可以避免这种延迟。因为我总是在我的三星手机上开发,它默认配置了自己的专有 TTS,所以直到我在其他品牌手机上检查了我的应用程序时,我才注意到这个问题,这些手机默认配置了 Google TTS 引擎。但是,理想情况下,我不想强​​迫用户安装另一个应用程序以及我自己的应用程序,因此我希望它与默认的 Google TTS 引擎本身一起使用。

通过我后来更正的一些错误编码,我意识到如果我可以保持 TextToSpeech 对象事先初始化并且始终不为空——一旦初始化,我似乎可以绕过这个延迟。

但是,由于一旦我们完成资源就需要关闭资源,我无法让对象长时间保持 Activity 和初始化,而且我不知道何时初始化/关闭资源,因为我在技术上需要特定事件发生时播放的语音,主要是当我的应用程序未在手机上打开时。

所以我的问题如下:
  • 我们能否以某种方式减少或消除初始化延迟
    Google TTS 引擎,以编程方式还是以其他方式?
  • 有什么方法可以保留 TextToSpeech 对象
    存活并初始化 任何时候比如说,通过服务?
    或者这会是一个糟糕的、消耗资源的设计吗?
  • 也是使用静态 TextToSpeech 对象的正确方法,
    满足我的要求?

  • 任何解决方案以及代码将不胜感激。

    更新:我已经确认延迟仅与 Google TTS 引擎相关,因为我尝试使用其他免费和付费 TTS 引擎,其中几乎没有延迟。但如果可能的话,我仍然希望没有任何第三方依赖项,并希望与 Google TTS 引擎一起使用。

    更新:我似乎通过将此 TTS 对象绑定(bind)到服务并从服务访问它来绕过这个问题。该服务是 STICKY(如果服务由于内存问题而终止,Android 操作系统将在内存再次可用时重新启动该服务)并配置为在设备重新启动时重新启动。

    该服务只初始化 TTS 对象,不做其他工作。我没有明确停止服务,让它尽可能长时间地运行。我已将 TTS 对象定义为静态对象,以便我可以从应用程序的其他类访问它。

    虽然这似乎工作得非常好,但我担心这是否会导致内存或电池问题(在我的特定情况下,服务仅处理对象初始化然后保持休眠状态)。我的设计是否有任何问题,或者是否可以对我的设计进行任何进一步的改进/检查?

    list 文件:
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>


    <application
    android:allowBackup="false"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
    <activity
    android:name="activity.MainActivity"
    android:label="@string/app_name"
    android:screenOrientation="portrait" >
    <intent-filter>
    <action android:name="android.intent.action.MAIN" />

    <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    </activity>

    <receiver
    android:name="services.BroadcastReceiverOnBootComplete"
    android:enabled="true"
    android:exported="false">
    <intent-filter>
    <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
    <intent-filter>
    <action android:name="android.intent.action.PACKAGE_REPLACED" />
    <data android:scheme="package" />
    </intent-filter>
    <intent-filter>
    <action android:name="android.intent.action.PACKAGE_ADDED" />
    <data android:scheme="package" />
    </intent-filter>
    </receiver>


    <service android:name="services.TTSService"></service>

    广播接收器代码:
    public class BroadcastReceiverOnBootComplete extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
    if (intent.getAction().equalsIgnoreCase(Intent.ACTION_BOOT_COMPLETED)) {
    Intent serviceIntent = new Intent(context, TTSService.class);
    context.startService(serviceIntent);
    }
    }

    }

    TTS服务代码:
    public class TTSService extends Service {

    private static TextToSpeech voice =null;

    public static TextToSpeech getVoice() {
    return voice;
    }

    @Nullable
    @Override

    public IBinder onBind(Intent intent) {
    // not supporting binding
    return null;
    }

    public TTSService() {
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

    try{
    Log.d("TTSService","Text-to-speech object initializing");

    voice = new TextToSpeech(TTSService.this,new TextToSpeech.OnInitListener() {
    @Override
    public void onInit(final int status) {
    Log.d("TTSService","Text-to-speech object initialization complete");

    }
    });

    }
    catch(Exception e){
    e.printStackTrace();
    }


    return Service.START_STICKY;
    }

    @Override
    public void onDestroy() {
    clearTtsEngine();
    super.onDestroy();

    }

    public static void clearTtsEngine()
    {
    if(voice!=null)
    {
    voice.stop();
    voice.shutdown();
    voice = null;
    }



    }
    }

    修改后的 VoiceGenerator 代码:
    public class VoiceGenerator {

    private TextToSpeech voice = null;

    public VoiceGenerator(Context context)
    {
    this.context = context;
    }


    public void voiceInit(String text)
    {
    try {
    if (voice == null) {

    new Thread(new Runnable() {
    @Override
    public void run() {

    voice = TTSService.getVoice();
    if(voice==null)
    return;

    voice.setLanguage(Locale.US);
    HashMap p = new HashMap<String, String>();
    p.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "ThisUtterance");
    voice.speak(text, TextToSpeech.QUEUE_ADD, p);

    voice.setOnUtteranceProgressListener(new UtteranceProgressListener() {
    @Override
    public void onStart(String utteranceId) {

    }

    @Override
    public void onDone(String utteranceId) {
    }

    @Override
    public void onError(String utteranceId) {

    }
    });
    }
    }).start();

    }
    }
    catch(Exception e)
    {
    Log.d("ErrorLog","Error occurred while voice play");
    e.printStackTrace();
    }
    }




    }

    最佳答案

    我是 Android 应用程序 Saiy 的开发人员。这不是一个无耻的插件,它是为了证明我使用了您正在考虑的设计模式,并且我已经“经历”了促使您提出问题的原因。

    这让我内存犹新,因为去年我一直在重写我的代码,并且不得不认真考虑周围的问题。

  • 我们能否以编程方式或其他方式减少或消除 Google TTS 引擎的初始化延迟?

  • 我问了 similar question some time ago并在不与其他任务竞争的后台线程上初始化 Text to Speech 对象,可以稍微减少延迟(正如我在发布的代码中看到的那样)。

    您还可以通过选择嵌入的语音而不是依赖于网络的语音来确保发言请求不会被进一步延迟:

    在 API 21+ 中查看 Voice class 上的选项.特别 getFeatures()您可以在其中检查网络的延迟和要求。

    在 API <21 - 设置 KEY_FEATURE_NETWORK_SYNTHESIS在您的参数中设置为 false。

    不管上述情况如何,Google TTS 引擎在我测试过的所有引擎中的初始化时间最长(我认为是所有引擎)。我相信这仅仅是因为他们正在使用设备上的所有可用资源来提供最高质量的语音。

    从我自己的个人测试来看,这个延迟与设备的硬件成正比。处理器的 RAM 和性能越高,初始化时间就越短。设备的当前状态也是如此——我想你会发现在重新启动后,如果有空闲内存并且 Android 不需要杀死其他进程,初始化时间就会减少。

    综上所述,除上述之外, ,你不能减少初始化时间。
  • 有什么方法可以让 TextToSpeech 对象始终保持 Activity 状态并进行初始化,例如通过服务?或者这会是一个糟糕的、消耗资源的设计吗?
  • 对于我的要求,使用静态 TextToSpeech 对象也是正确的方法吗?

  • 正如您所指出的,避免初始化时间的一种方法是保持与引擎的绑定(bind)。但是,在执行此操作之前,您可能希望考虑更多问题。

    如果设备处于需要释放资源的状态,这与导致初始化延迟延长的状态相同,Android 完全有权对这个绑定(bind)进行垃圾收集。如果您在后台服务中持有此绑定(bind),则该服务可能会被终止,让您回到原点。

    此外,如果您仍然绑定(bind)到引擎,您的用户将在 Android 运行的应用程序设置中看到集体内存使用情况。对于许多错误地认为(休眠)内存使用与电池消耗成正比的用户,根据我的经验,这将导致卸载和应用程序评级不佳。

    在撰写本文时,Google TTS 以 70mb 的成本绑定(bind)到我的应用程序。

    如果您仍然想在此基础上继续,您可以尝试让 Android 优先处理您的进程并最后终止它 - 您可以通过使用前台服务来做到这一点。不过,这会打开另一 jar 蠕虫,我不会深入研究。

    实际上,当您希望引擎发言时,绑定(bind)到服务中的引擎并检查服务是否正在运行,是一种“单例模式”。在此服务中使引擎静态不会有任何我能想到的用途。

    你可以看到 here我如何开始处理 TTS 初始化以及可能发生的相关问题 - 包括滞后。

    最后 ,分享我如何处理上述问题的经验。

    我在应用程序中的“已知错误”和“常见问题解答”顶部显示“Google 初始化缓慢”。

    我监控引擎调用 onInit 所需的时间.如果时间太长,我会向用户发出通知并将他们引导至常见问题解答,在那里温和地建议他们尝试另一个 TTS 引擎。

    我运行一个后台计时器,它会在一段时间不 Activity 后释放引擎。这段时间可由用户配置,并带有初始化延迟警告......

    我知道以上内容并不能解决您的问题,但也许我的建议会安抚您的用户,这与解决问题相差甚远,但是嘿...

    我毫不怀疑 Google 会逐渐提高初始化性能——四年前,我遇到了 IVONA 的这个问题,他们最终在初始化时间上做得很好。

    关于android - 绕过 Android 中的 Google TTS 引擎初始化延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42417606/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com