草庐IT

android - KitKat 在第一次调用时比 Froyo 多花 6 秒对 TextToSpeech.speak() 使用react

coder 2023-12-17 原文

在运行最新版本 Android 的最新手机上,与旧手机相比,TextToSpeech 引擎在首次调用时可能需要大约 6 秒的时间才能使用react。

我的测试代码如下所示。 (已编辑:Android 4.0.3 Ice Cream Sandwich、API 15 及更高版本的替代代码,最后显示。)

在运行 4.4.4 KitKat 的 1 岁摩托罗拉 Moto G 上,TextToSpeech 引擎可能需要 7 秒以上才能完成对 speak() 单词“Started”的首次调用。这是我的代码的输出。

D/speak﹕ call: 1415501851978
D/speak﹕ done: 1415501859122, delay: 7144

在运行 2.2 Froyo 的 3 岁三星 SGH-T499Y 上,不到一秒钟就可以完成说话:

D/speak﹕ call: 1415502283050
D/speak﹕ done: 1415502283900, delay: 850

有没有办法发现这 6 秒延迟期间发生了什么?
有什么方法可以让更新的(而且据说更快的)设备更快地使用react吗?

package com.example.speak

import android.app.Activity;
import android.speech.tts.TextToSpeech;
import android.os.Bundle;
import android.util.Log;

import java.util.HashMap;
import java.util.Locale;


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

    private final String TAG = "speak";
    private Activity activity;
    private TextToSpeech tts;
    private long launchTime;

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

        tts = new TextToSpeech(getApplicationContext(), this);
    }

    public void onInit(int status) {
        if (status == TextToSpeech.SUCCESS) {
            tts.setOnUtteranceCompletedListener(this);
            tts.setLanguage(Locale.UK);
            ttsSay("Started");
        }
    }

    private void ttsSay(String toSpeak) {
        int mode = TextToSpeech.QUEUE_FLUSH;
        HashMap hashMap = new HashMap<String, String>();
        hashMap.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, TAG);

        launchTime = System.currentTimeMillis();
        Log.d(TAG, "call: " + launchTime);
        tts.speak(toSpeak, mode, hashMap);
    }

    public void onUtteranceCompleted(String utteranceID) {
        long millis = System.currentTimeMillis();
        Log.d(TAG, "done: " + millis + ", delay: " + (millis - launchTime));
    }
}

编辑:从 Ice Cream Sandwich 4.0.3、API 15 开始,Android 提供 UtteranceProgressListener ,可用于为文本转语音播放的开始和结束计时。以下内容与 Froyo 不兼容;

package com.example.announceappprogress;

import android.app.Activity;
import android.speech.tts.TextToSpeech;
import android.os.Bundle;
import android.speech.tts.UtteranceProgressListener;
import android.util.Log;

import java.util.HashMap;
import java.util.Locale;


public class MainActivity extends Activity implements TextToSpeech.OnInitListener {

    private final String TAG = "speak";
    private TextToSpeech tts;
    private long launchTime;
    private long startTime;


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

        tts = new TextToSpeech(getApplicationContext(), this);
        tts.setOnUtteranceProgressListener(mProgressListener);
    }

    public void onInit(int status) {
        if (status == TextToSpeech.SUCCESS) {
            tts.setLanguage(Locale.UK);
            ttsSay("Started");
        }
    }

    private void ttsSay(String toSpeak) {
        int mode = TextToSpeech.QUEUE_FLUSH;
        HashMap hashMap = new HashMap<String, String>();
        hashMap.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, TAG);

        launchTime = System.currentTimeMillis();
        Log.d(TAG, "called: " + launchTime);
        tts.speak(toSpeak, mode, hashMap);
    }

    private final UtteranceProgressListener mProgressListener = new UtteranceProgressListener() {
        @Override
        public void onStart(String utteranceId) {
            startTime = System.currentTimeMillis();
            Log.d(TAG, "started: " + startTime + ", delay: " + (startTime - launchTime));
        }

        @Override
        public void onError(String utteranceId) {} // Do nothing.


        @Override
        public void onDone(String utteranceId) {
            long millis = System.currentTimeMillis();
            Log.d(TAG, "done: " + millis + ", total: " + (millis - launchTime) + ", duration: " + (millis - startTime));
        }
    };
}

这是在运行 4.4.4 KitKat 的摩托罗拉 Moto G 上给出的输出示例:

D/speak﹕ called:  1415654293442
D/speak﹕ started: 1415654299287, delay: 5845
D/speak﹕ done:    1415654299995, total: 6553, duration: 708

最佳答案

您可能没有在两台设备上使用相同的 TTS 引擎。

更多人声拼接 TTS 引擎(您可能已经安装在较新的设备上)可以使用数百兆字节的数据文件来生成语音。这些系统中的大多数都需要一定的设置时间才能发出第一句话。简单的(听起来更机械化的)基于共振峰的系统可能只需要几兆字节,因此加载速度要快得多。

一个有趣的实验是为“第二个”话语计时。我预计这会比您的新手机上的第一个更快。此外,听起来更自然的 TTS 系统通常在调用 TTS 和从话语开始发出声音之间具有更长的延迟时间。特别是如果给出了一个长句子,因为系统会在开始说话之前检查整个句子以制定最佳措辞。

此外,您确定您的新设备没有使用某些基于云的 TTS 服务吗?还有其他重要的、额外的变量会影响延迟。

关于android - KitKat 在第一次调用时比 Froyo 多花 6 秒对 TextToSpeech.speak() 使用react,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26824649/

有关android - KitKat 在第一次调用时比 Froyo 多花 6 秒对 TextToSpeech.speak() 使用react的更多相关文章

  1. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  2. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

  3. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  4. ruby-on-rails - Rake 任务仅调用一次时执行两次 - 2

    我写了一个非常简单的rake任务来尝试找到这个问题的根源。namespace:foodotaskbar::environmentdoputs'RUNNING'endend当在控制台中执行rakefoo:bar时,输出为:RUNNINGRUNNING当我执行任何rake任务时会发生这种情况。有没有人遇到过这样的事情?编辑上面的rake任务就是写在那个.rake文件中的所有内容。这是当前正在使用的Rakefile。requireFile.expand_path('../config/application',__FILE__)OurApp::Application.load_tasks这里

  5. ruby - 我怎样才能只写一次 "Text"并同时检查 path_info 是否包含 'A' ? - 2

    -if!request.path_info.include?'A'%{:id=>'A'}"Text"-else"Text"“文本”写了两次。我怎样才能只写一次并同时检查path_info是否包含“A”? 最佳答案 有两种方法可以做到这一点。使用部分,或使用content_forblock:如果“文本”较长,或者是一个重要的子树,您可以将其提取到一个部分。这会使您的代码变干一点。在给出的示例中,这似乎有点矫枉过正。在这种情况下更好的方法是使用content_forblock,如下所示:-if!request.path_info.inc

  6. ruby-on-rails - Ruby 长时间运行的进程对队列事件使用react - 2

    我有一个将某些事件写入队列的Rails3应用。现在我想在服务器上创建一个服务,每x秒轮询一次队列,并按计划执行其他任务。除了创建ruby​​脚本并通过cron作业运行它之外,还有其他稳定的替代方案吗? 最佳答案 尽管启动基于Rails的持久任务是一种选择,但您可能希望查看更有序的系统,例如delayed_job或Starling管理您的工作量。我建议不要在cron中运行某些东西,因为启动整个Rails堆栈的开销可能很大。每隔几秒运行一次它是不切实际的,因为Rails上的启动时间通常为5-15秒,具体取决于您的硬件。不过,每天这样做几

  7. ruby-on-rails - 使用 Ruby 正确处理 Stripe 错误和异常以实现一次性收费 - 2

    我查看了Stripedocumentationonerrors,但我仍然无法正确处理/重定向这些错误。基本上无论发生什么,我都希望他们返回到edit操作(通过edit_profile_path)并向他们显示一条消息(无论成功与否)。我在edit操作上有一个表单,它可以POST到update操作。使用有效的信用卡可以正常工作(费用在Stripe仪表板中)。我正在使用Stripe.js。classExtrasController5000,#amountincents:currency=>"usd",:card=>token,:description=>current_user.email)

  8. ruby - 从 ruby​​ 调用时返回 shell 脚本的状态值? - 2

    我希望这些值匹配。当shell脚本由于某些错误条件而退出时(因此返回非零值),它们不匹配。壳$?返回1,ruby$?返回256。>>%x[lskkr]ls:kkr:Nosuchfileordirectory=>"">>puts$?256=>nil>>exitHadoop:~Madcap$lskkrls:kkr:NosuchfileordirectoryHadoop:~Madcap$echo$?1 最佳答案 在Ruby中$?是一个Process::Status实例。打印$?等同于调用$?.to_s,这等同于$?.to_i.to_s(来

  9. ruby - 如何在 Ruby 中只执行一次方法?有静态变量吗? - 2

    我写了一个脚本,其中包含一些方法定义,没有类和一些公共(public)代码。其中一些方法执行一些非常耗时的shell程序。然而,这些shell程序只需要在第一次调用该方法时执行。现在在C中,我会在每个方法中声明一个静态变量,以确保这些程序只执行一次。我怎么能在Ruby中做到这一点? 最佳答案 ruby中有一个成语:x||=y。defsomething@something||=calculate_somethingendprivatedefcalculate_something#somelongprocessend但是如果您的“长时间

  10. ruby - 格式化数字以每隔三位数拆分一次 - 2

    我想在格式化数字时每隔三个字符放置一个空格。根据这个规范:it"shouldformatanamount"dospaces_on(1202003).should=="1202003"end我想出了这段代码来完成这项工作defspaces_onamountthousands=amount/1000remainder=amount%1000ifthousands==0"#{remainder}"elsezero_padded_remainder='%03.f'%remainder"#{spaces_onthousands}#{zero_padded_remainder}"endend所以我

随机推荐