Web语音API:在iOS safari上一致获取支持的语音合成声音

2023-11-25

我正在尝试获取 iOS Safari 上支持的语音合成声音列表。

根据 API,我应该能够通过调用获取一系列声音:

window.speechSynthesis.getVoices();

有时这会给我声音列表,有时则不会。请参阅以下 jsfiddle:https://jsfiddle.net/sq7xf327/

如果我在 iPhone 5 (iOS 8.1.3) 上打开它,我不会得到一致的结果。有时我会返回所有 37 个语音,有时我会返回 0 个语音。如果继续刷新,它偶尔会显示 37 或 0。

我知道在 Chrome 中你可以添加一个事件监听器

window.speechSynthesis.voiceschanged 

事件来了解语音何时加载,但 Safari 不支持此事件。

我尝试过的一个技巧是定期检查:

var timer = setInterval(function () {
    window.voices_ = window.speechSynthesis.getVoices();
    if (window.voices_.length > 0) {
        clearInterval(timer);
    }
}, 1000);

这也没有给我带来一致的结果。

知道如何在 iOS Safari 上可靠且一致地获取支持的语音合成语音吗?


我也遇到过这个问题,并将其作为错误报告给Apple。截至今天,错误报告仍然开放。

我最终做的解决方法是对 37 个声音的数组进行硬编码。如果speechSynthesis.getVoices()返回一个空数组,然后使用硬编码数组。

var _voices = [];

// iOS 8
var _iOSvoices = [
    {name: "pt-BR", voiceURI: "pt-BR", lang: "pt-BR", localService: true, default: true},
    {name: "fr-CA", voiceURI: "fr-CA", lang: "fr-CA", localService: true, default: true},
    {name: "sk-SK", voiceURI: "sk-SK", lang: "sk-SK", localService: true, default: true},
    {name: "th-TH", voiceURI: "th-TH", lang: "th-TH", localService: true, default: true},
    {name: "ro-RO", voiceURI: "ro-RO", lang: "ro-RO", localService: true, default: true},
    {name: "no-NO", voiceURI: "no-NO", lang: "no-NO", localService: true, default: true},
    {name: "fi-FI", voiceURI: "fi-FI", lang: "fi-FI", localService: true, default: true},
    {name: "pl-PL", voiceURI: "pl-PL", lang: "pl-PL", localService: true, default: true},
    {name: "de-DE", voiceURI: "de-DE", lang: "de-DE", localService: true, default: true},
    {name: "nl-NL", voiceURI: "nl-NL", lang: "nl-NL", localService: true, default: true},
    {name: "id-ID", voiceURI: "id-ID", lang: "id-ID", localService: true, default: true},
    {name: "tr-TR", voiceURI: "tr-TR", lang: "tr-TR", localService: true, default: true},
    {name: "it-IT", voiceURI: "it-IT", lang: "it-IT", localService: true, default: true},
    {name: "pt-PT", voiceURI: "pt-PT", lang: "pt-PT", localService: true, default: true},
    {name: "fr-FR", voiceURI: "fr-FR", lang: "fr-FR", localService: true, default: true},
    {name: "ru-RU", voiceURI: "ru-RU", lang: "ru-RU", localService: true, default: true},
    {name: "es-MX", voiceURI: "es-MX", lang: "es-MX", localService: true, default: true},
    {name: "zh-HK", voiceURI: "zh-HK", lang: "zh-HK", localService: true, default: true},
    {name: "sv-SE", voiceURI: "sv-SE", lang: "sv-SE", localService: true, default: true},
    {name: "hu-HU", voiceURI: "hu-HU", lang: "hu-HU", localService: true, default: true},
    {name: "zh-TW", voiceURI: "zh-TW", lang: "zh-TW", localService: true, default: true},
    {name: "es-ES", voiceURI: "es-ES", lang: "es-ES", localService: true, default: true},
    {name: "zh-CN", voiceURI: "zh-CN", lang: "zh-CN", localService: true, default: true},
    {name: "nl-BE", voiceURI: "nl-BE", lang: "nl-BE", localService: true, default: true},
    {name: "en-GB", voiceURI: "en-GB", lang: "en-GB", localService: true, default: true},
    {name: "ar-SA", voiceURI: "ar-SA", lang: "ar-SA", localService: true, default: true},
    {name: "ko-KR", voiceURI: "ko-KR", lang: "ko-KR", localService: true, default: true},
    {name: "cs-CZ", voiceURI: "cs-CZ", lang: "cs-CZ", localService: true, default: true},
    {name: "en-ZA", voiceURI: "en-ZA", lang: "en-ZA", localService: true, default: true},
    {name: "en-AU", voiceURI: "en-AU", lang: "en-AU", localService: true, default: true},
    {name: "da-DK", voiceURI: "da-DK", lang: "da-DK", localService: true, default: true},
    {name: "en-US", voiceURI: "en-US", lang: "en-US", localService: true, default: true},
    {name: "en-IE", voiceURI: "en-IE", lang: "en-IE", localService: true, default: true},
    {name: "he-IL", voiceURI: "he-IL", lang: "he-IL", localService: true, default: true},
    {name: "hi-IN", voiceURI: "hi-IN", lang: "hi-IN", localService: true, default: true},
    {name: "el-GR", voiceURI: "el-GR", lang: "el-GR", localService: true, default: true},
    {name: "ja-JP", voiceURI: "ja-JP", lang: "ja-JP", localService: true, default: true}
];

function populateVoices() {
    // wait first
    var watch = setTimeout(function() {
        _voices = speechSynthesis.getVoices();

        if (_voices.length === 0) {
            // use hard-coded list because speechSynthesis.getVoices() didn't work
            _voices = _iOSvoices;
        }

        clearTimeout(watch);
    }, 100);
}

UPDATE

如果消除延迟,iOS 9 在这方面会更好一些。

function _populateVoices() {
    _voices = speechSynthesis.getVoices();

    if (_voices.length === 0) {
        // use hard-coded list because speechSynthesis.getVoices() didn't work
        _voices = _iOS9voices;
    }
}

var _iOS9voices = [
  { name: "Maged", voiceURI: "com.apple.ttsbundle.Maged-compact", lang: "ar-SA", localService: true, "default": true },
  { name: "Zuzana", voiceURI: "com.apple.ttsbundle.Zuzana-compact", lang: "cs-CZ", localService: true, "default": true },
  { name: "Sara", voiceURI: "com.apple.ttsbundle.Sara-compact", lang: "da-DK", localService: true, "default": true },
  { name: "Anna", voiceURI: "com.apple.ttsbundle.Anna-compact", lang: "de-DE", localService: true, "default": true },
  { name: "Melina", voiceURI: "com.apple.ttsbundle.Melina-compact", lang: "el-GR", localService: true, "default": true },
  { name: "Karen", voiceURI: "com.apple.ttsbundle.Karen-compact", lang: "en-AU", localService: true, "default": true },
  { name: "Daniel", voiceURI: "com.apple.ttsbundle.Daniel-compact", lang: "en-GB", localService: true, "default": true },
  { name: "Moira", voiceURI: "com.apple.ttsbundle.Moira-compact", lang: "en-IE", localService: true, "default": true },
  { name: "Samantha (Enhanced)", voiceURI: "com.apple.ttsbundle.Samantha-premium", lang: "en-US", localService: true, "default": true },
  { name: "Samantha", voiceURI: "com.apple.ttsbundle.Samantha-compact", lang: "en-US", localService: true, "default": true },
  { name: "Tessa", voiceURI: "com.apple.ttsbundle.Tessa-compact", lang: "en-ZA", localService: true, "default": true },
  { name: "Monica", voiceURI: "com.apple.ttsbundle.Monica-compact", lang: "es-ES", localService: true, "default": true },
  { name: "Paulina", voiceURI: "com.apple.ttsbundle.Paulina-compact", lang: "es-MX", localService: true, "default": true },
  { name: "Satu", voiceURI: "com.apple.ttsbundle.Satu-compact", lang: "fi-FI", localService: true, "default": true },
  { name: "Amelie", voiceURI: "com.apple.ttsbundle.Amelie-compact", lang: "fr-CA", localService: true, "default": true },
  { name: "Thomas", voiceURI: "com.apple.ttsbundle.Thomas-compact", lang: "fr-FR", localService: true, "default": true },
  { name: "Carmit", voiceURI: "com.apple.ttsbundle.Carmit-compact", lang: "he-IL", localService: true, "default": true },
  { name: "Lekha", voiceURI: "com.apple.ttsbundle.Lekha-compact", lang: "hi-IN", localService: true, "default": true },
  { name: "Mariska", voiceURI: "com.apple.ttsbundle.Mariska-compact", lang: "hu-HU", localService: true, "default": true },
  { name: "Damayanti", voiceURI: "com.apple.ttsbundle.Damayanti-compact", lang: "id-ID", localService: true, "default": true },
  { name: "Alice", voiceURI: "com.apple.ttsbundle.Alice-compact", lang: "it-IT", localService: true, "default": true },
  { name: "Kyoko", voiceURI: "com.apple.ttsbundle.Kyoko-compact", lang: "ja-JP", localService: true, "default": true },
  { name: "Yuna", voiceURI: "com.apple.ttsbundle.Yuna-compact", lang: "ko-KR", localService: true, "default": true },
  { name: "Ellen", voiceURI: "com.apple.ttsbundle.Ellen-compact", lang: "nl-BE", localService: true, "default": true },
  { name: "Xander", voiceURI: "com.apple.ttsbundle.Xander-compact", lang: "nl-NL", localService: true, "default": true },
  { name: "Nora", voiceURI: "com.apple.ttsbundle.Nora-compact", lang: "no-NO", localService: true, "default": true },
  { name: "Zosia", voiceURI: "com.apple.ttsbundle.Zosia-compact", lang: "pl-PL", localService: true, "default": true },
  { name: "Luciana", voiceURI: "com.apple.ttsbundle.Luciana-compact", lang: "pt-BR", localService: true, "default": true },
  { name: "Joana", voiceURI: "com.apple.ttsbundle.Joana-compact", lang: "pt-PT", localService: true, "default": true },
  { name: "Ioana", voiceURI: "com.apple.ttsbundle.Ioana-compact", lang: "ro-RO", localService: true, "default": true },
  { name: "Milena", voiceURI: "com.apple.ttsbundle.Milena-compact", lang: "ru-RU", localService: true, "default": true },
  { name: "Laura", voiceURI: "com.apple.ttsbundle.Laura-compact", lang: "sk-SK", localService: true, "default": true },
  { name: "Alva", voiceURI: "com.apple.ttsbundle.Alva-compact", lang: "sv-SE", localService: true, "default": true },
  { name: "Kanya", voiceURI: "com.apple.ttsbundle.Kanya-compact", lang: "th-TH", localService: true, "default": true },
  { name: "Yelda", voiceURI: "com.apple.ttsbundle.Yelda-compact", lang: "tr-TR", localService: true, "default": true },
  { name: "Ting-Ting", voiceURI: "com.apple.ttsbundle.Ting-Ting-compact", lang: "zh-CN", localService: true, "default": true },
  { name: "Sin-Ji", voiceURI: "com.apple.ttsbundle.Sin-Ji-compact", lang: "zh-HK", localService: true, "default": true },
  { name: "Mei-Jia", voiceURI: "com.apple.ttsbundle.Mei-Jia-compact", lang: "zh-TW", localService: true, "default": true }
];
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Web语音API:在iOS safari上一致获取支持的语音合成声音 的相关文章

  • 使用 UITabBarController 时覆盖整个屏幕的视图?

    我想在 UITabBarController 设置中在整个屏幕上覆盖 HUD 样式的透明图形 执行此操作的按钮位于第一个选项卡的屏幕 FirstViewController 中 并且覆盖层也应该覆盖选项卡 这可能吗 您可以将新视图直接附加到
  • 引导程序提前输入未填充承诺的响应

    我的引导程序预输入如下
  • 根据内容自动更改单元格高度 - Swift

    在 Swift 中使用 UITableView 有人可以帮我根据标签 图片和描述自动更改单元格的高度吗 所有信息都正确传递 我只需要帮助格式化它 我尝试使用调整它cell frame size height 但这没有效果 我可以更改故事板中
  • 使用 dc.js 按条形值对条形图中的条形进行排序(排序)

    如何通过维度的计算值而不是维度本身的名称对 dc js 示例中的 x 轴 维度 进行排序 例如 请考虑序数条形图的 dc js 示例 https github com dc js dc js blob master web examples
  • 从现有坐标地图套件中查找最近的位置

    我正在为拥有多家商店的客户开发 iPhone 应用程序 目标 C 我有数组中所有商店 20 的坐标 纬度 长 目前我正在考虑循环遍历商店坐标数组并获取从用户当前位置到商店位置的距离 然后将它们添加到数组中并按最小距离进行排序 这是正确的方法
  • 如何解决 Typescript 构建中的错误“找不到模块 'jquery'”

    我目前在 ts 文件的顶部有这个import require jquery 我这样做是因为我试图在我的打字稿文件中使用 jquery 但我似乎无法编译它 因为它返回标题中所述的错误 我正在使用 ASP NET CORE 脚本文件夹 tsco
  • window.location 和 location.href 之间的区别

    我对之间的区别感到困惑window location and location href 两者似乎都以相同的方式行事 有什么不同 window location是一个对象 它保存有关当前文档位置的所有信息 主机 href 端口 协议等 lo
  • 为什么我们在打字稿中使用 HTMLInputElement ?

    我们为什么使用 document getElementById ipv as HTMLInputElement value 代替 document getElementById ipv value 功能getElementById返回具有类
  • 将 UMD Javascript 模块导入浏览器

    你好 我正在对 RxJS 进行一些研究 我可以通过在浏览器中引用它来使用该库 如下所示 它使用全局对象命名空间变量 Rx 导入 我可以制作可观察的东西并做所有有趣的事情 当我将 src 更改为指向最新的 UMD 文件时 一切都会崩溃 如下所
  • 有没有办法在 onclick 触发时禁用 iPad/iPhone 上的闪烁/闪烁?

    所以我有一个有 onclick 事件的区域 在常规浏览器上单击时 它不会显示任何视觉变化 但在 iPad iPhone 上单击时 它会闪烁 闪烁 有什么办法可以阻止它在 iPad iPhone 上执行此操作吗 这是一个与我正在做的类似的示例
  • ios8 键盘高度有所不同

    我使用下面的代码来获取键盘高度 该高度在带有 ios8 的 iPhone 5s 设备中与带有 ios7 的 IPhone4s 设备中有所不同 因此 当我在带有 ios8 的 iPhone5s 中点击它时 我的文本字段移动得非常高 而相同的代
  • 在移动设备上滚动

    这个问题更多的是一个建议研究 我确实希望它对其他人有帮助 并且它不会关闭 因为我不太确定在哪里寻求有关此事的建议 在过去的 6 个月里 我一直在进行移动开发 我有机会处理各种设备上的各种情况和错误 最麻烦的是滚动问题 当涉及到在网站的多个区
  • 代码镜像错误:未捕获错误:扩展集中无法识别扩展值([对象对象])

    全部 我目前正在从事一个React Electron项目 该项目的目标是完成一个Markdown编辑器 当我配置codemirror 该程序报告错误说 Uncaught Error Unrecognized extension value
  • 使用强光混合模式时突出显示伪影

    我正在 iPhone 应用程序中使用顶部图像的 HardLight 混合模式混合两个图像 它看起来像这样 UIGraphicsBeginImageContext size sourceImage drawInRect rectangle b
  • 对于只触及我的工作表的 Google 表格脚本,收到“此应用程序未经验证”

    我正在编写一个 Google Sheets 脚本 我只想访问与 gs 文件关联的同一电子表格中的数据 似乎我应该有权在自己的电子表格中运行脚本 但是每当我运行一个函数时 我都会得到一个This app isn t verified信息 我该
  • 带参数的事件监听器

    我想将参数传递给 JavaScript 中的事件侦听器 我已经找到了解决方案 但我无法理解它们为什么或如何工作以及为什么其他解决方案不起作用 我有 C C 背景 但是 Javascript 函数的执行有很大不同 您能否帮助我理解以下示例如何
  • Fitbit oauth2 公共 API 停止工作。给出错误 - 抱歉,这不是你..是我们

    几个月前 我准备了一个关于 Fitbit oauth2 公共 API 的演示 其中我使用特定用户登录并获取他的活动 一切正常 但最近 我打开演示并尝试使用同一用户登录 但它没有登录并反复出现此错误 我尝试更改在 Fitbit 上注册的演示应
  • 从 FileReader 设置背景图像样式

    我正在寻找一种解决方案 允许我从文件上传输入中获取文件并通过设置 document body style backgroundImage 来预览它 以下代码用于在 Image 元素中显示预览 function setImage id tar
  • JavaScript 相对路径

    在第一个 html 文件中 我使用了一个变量类别链接 var categoryLinks Career prospects http localhost Landa DirectManagers 511 HelenaChechik Dim0
  • Vue.js[vuex] 如何从突变中调度?

    我有一个要应用于 json 对象的过滤器列表 我的突变看起来像这样 const mutations setStars state payload state stars payload this dispatch filter setRev

随机推荐

  • 如何在我的应用程序中手动包含 VCL 样式?

    我有一个应用程序 它使用条件能够将其编译为 VCL 表单应用程序或 Delphi XE2 中的 Windows 服务应用程序 但是 由于我手动更改了项目的主源文件 IDE 将不再允许我使用标准项目选项窗口进行某些修改 具体来说 我无法选择要
  • 如何在 string.replace 中输入正则表达式?

    我需要一些关于声明正则表达式的帮助 我的输入如下 this is a paragraph with lt 1 gt in between and then there are cases where the lt 99 gt number
  • XMLHttpRequest upload.onprogress 立即完成

    我正在尝试使用 HTML5 制作一个带有进度表的文件上传器 这是我的代码
  • C++/CLI:相对于 C# 的优势

    与 C 相比 托管 C CLI 有什么主要优势吗 绝对不是我认为的语法 因为 C CLI 中的以下代码非常丑陋 C CLI 代码 Out List
  • 日志方法之间的区别

    我是 android 新手 我使用以下方法打印 log cat Log w Tag String text 并记录文本打印 但经过一段时间的搜索后 我找到了更多打印 logcat 的方法 例如 Log v Log d 现在我对这些方法感到困
  • 跨 JavaEE Web 服务使用单个 MongoClient

    在阅读了 mongo 文档后 该文档说 MongoClient 的每个实例都处理自己的池 我该如何在整个应用程序中只拥有一个实例呢 这看起来可能是使用单例 bean 的场景 但这似乎会违背连接池的目的 如果一次只有一个用户能够访问包含 Mo
  • 传递给 pytest 夹具的参数可以作为变量传递吗?

    我有两个简单的测试设置 我试图将它们分组到一个夹具中 并希望测试函数将 参数 传递给夹具 这是一个人为的例子 来解释我的问题 假设我有以下 pytest 夹具 pytest fixture scope module params param
  • DataTable.Select日期格式问题

    我正在使用 DataTable Select 在日期范围内过滤数据表 我的条件字符串是 CreatedOn gt 03 11 2009 00 00 00 AND CreatedOn lt 03 11 2009 23 59 00 此过滤器不返
  • UnicodeEncodeError:“ascii”编解码器无法对特殊名称的字符进行编码[重复]

    这个问题在这里已经有答案了 我的 python 版本 2 7 脚本运行良好 可以从本地 html 文件获取一些公司名称 但是当涉及到某些特定的国家 地区名称时 它会给出此错误 UnicodeEncodeError ascii 编解码器无法编
  • rgba 在 IE9 中不工作

    由于某种原因 我无法使用 IE9 在 CSS 中使用 rgba 我已经使用 Chrome 进行了测试 效果很好 不知道出了什么问题 我的 HTML 是
  • Eclipse + Maven:强制执行环境“JavaSE-1.6”而不是固定的JDK

    我使用 Eclipse 作为 IDE 并在其外部使用 Maven 以使所有依赖项保持最新并更新 Eclipse 项目 在 Eclipse 中 我通常指定 JRE 系统库作为任何 Java 项目的执行环境 通常是 JavaSE 1 6 在 p
  • CSS 将文本旋转 n 度,但不旋转边界框?

    我知道 CSStransform rotate属性 以及用于制作有角度的方法div元素 但有一个非常重要的设计元素我无法在任何地方找到解决 如何保持边界框的角度 当我创建有角度的 div 元素时 我使用一个旋转的包装元素n度数 然后是子元素
  • C#:如何使用类型转换器本地化枚举

    阅读后我试图了解如何使用类型转换器这个答案我的其他问题之一 但我不确定我是否完全明白 在我的特定情况下 我想通过根据枚举成员是什么来获取资源字符串 将枚举成员 转换 为本地化字符串 例如 如果我有这个枚举 public enum Sever
  • Mongo复杂排序?

    我知道如何按多个字段对 MongoDB 中的查询进行排序 例如 db coll find sort a 1 b 1 我可以使用用户定义的函数进行排序吗 例如 假设 a 和 b 是整数 则通过 a 和 b 之间的差 a b Thanks UP
  • 如何安装特定版本的 Erlang/OTP?

    我继承了一个带有木偶 流浪者 虚拟框设置的项目 vagrant 的规定正在破坏我的 erlangs 周围的rabbitmq server 错误 gt default err Stage main Rabbitmq Install Packa
  • TensorFlow:兼容性弃用警告

    注意 我的第一个问题在这里 请原谅缺乏细节或信息 如果需要的话 我们非常乐意澄清 我在 Mac 上运行 TensorFlow 1 0 0 并且在使用 learn Estimator 类时不断收到此警告 警告 tensorflow 来自 25
  • 使用React手动刷新react-query onClick

    当我重新获取查询时 当我有 onClick 按钮时 它会进入 正在更新 状态 但我希望重新获取查询并显示 正在加载 状态 我的代码是 https stackblitz com edit react ts jfq8ve file index
  • php chmod() 不更改权限

    我的图片上传脚本有问题 我知道有数百个相同的问题 但我还没有找到适合我的问题 upload dir images postcards chmod upload dir 777 if is writable upload dir echo T
  • 永久代是堆的一部分还是位于 jvm 中的不同空间中

    我看到了很多关于这个问题的评论 有人说是 有人说不是 而且许多答案都是模棱两可的 任何人都可以用更简单的术语描述它所在的位置吗 在一篇文章中 我什至看到有人说它与类内存共享相同的内存位置 其中类由类加载器加载 这是真的吗 原始 可能是错误的
  • Web语音API:在iOS safari上一致获取支持的语音合成声音

    我正在尝试获取 iOS Safari 上支持的语音合成声音列表 根据 API 我应该能够通过调用获取一系列声音 window speechSynthesis getVoices 有时这会给我声音列表 有时则不会 请参阅以下 jsfiddle