Highlight
Apple 在 AVSpeechSynthesizer 中加入
prefersAssistiveTechnologySettings,让应用语音可以沿用当前 VoiceOver 等辅助技术的声音、语速和音高设置。
核心内容
很多应用想加语音,第一反应是直接创建一个 AVSpeechSynthesizer。这在地图播报方向、AAC(Augmentative Alternative Communication,增强和替代沟通)应用、低视力用户的环境描述工具里很合理,因为这些体验本身就围绕语音展开,应用需要决定何时说、说什么、用什么声音说。
同一套做法放到屏幕阅读场景里会出问题。用户已经在使用 VoiceOver 或其他辅助技术时,应用再用 AVSpeechSynthesizer 自己播报,可能绕过用户为辅助技术配置的声音和语速。Session 一开始先划清边界:如果只是给 VoiceOver 用户补充少量事件描述,应通过 UIAccessibility.post(notification: .announcement, ...) 把请求交给正在运行的辅助技术。
真正需要 AVSpeechSynthesizer 的场景,是应用语音体验本身有独立价值。iOS 14 的新点在这里:AVSpeechUtterance.prefersAssistiveTechnologySettings 可以请求使用当前辅助技术的语音设置。这样,Seeing AI 这类应用仍然能自己描述取景器里的对象,同时让播报听起来更接近用户正在使用的 VoiceOver。
Session 后半段继续处理两个实际问题。AAC 应用可能要让用户选择自己的声音、语速、音高和音量;通话中还要把合成语音送进电话或 FaceTime。音频较多的应用还要决定 speech 是否占用应用共享的 audio session,避免和音乐、视频、音效互相干扰。
详细内容
交给辅助技术播报临时事件
(01:25)当应用只需要为 VoiceOver 用户补充一个偶发事件,例如状态变化或操作完成,不需要自己创建本地屏幕阅读器。把 announcement 交给 UIAccessibility,VoiceOver 会管理这次播报。
UIAccessibility.post(notification: .announcement, argument: "Hello World")
关键点:
notification: .announcement表示这是一条要由当前辅助技术播出的公告。argument是要朗读的文本。- 这条路径适合少量补充语音,不适合构建以语音为中心的应用功能。
创建并保留 AVSpeechSynthesizer
(02:55)以语音为中心的功能需要应用自己控制播报。最小流程是创建 synthesizer、创建 utterance、调用 speak(_:)。讲者特别提醒,AVSpeechSynthesizer 对象要保留到语音结束。
self.synthesizer = AVSpeechSynthesizer()
let utterance = AVSpeechUtterance(string: "Hello World")
self.synthesizer.speak(utterance)
关键点:
AVSpeechSynthesizer()是负责调度语音的对象。AVSpeechUtterance(string:)包含要播报的文本。speak(utterance)把这次 utterance 交给 synthesizer 播出。self.synthesizer需要被实例保留,避免语音尚未结束对象就被释放。
沿用 VoiceOver 等辅助技术的语音设置
(04:08)默认情况下,AVSpeechSynthesizer 使用设备的 Accessibility Spoken Content 设置。iOS 14 新增的 prefersAssistiveTechnologySettings 可以请求使用当前正在运行的辅助技术设置,包括声音、语速和音高。
self.synthesizer = AVSpeechSynthesizer()
let utterance = AVSpeechUtterance(string: "Hello World")
utterance.prefersAssistiveTechnologySettings = true
self.synthesizer.speak(utterance)
关键点:
prefersAssistiveTechnologySettings = true写在AVSpeechUtterance上。- 当前有 VoiceOver 等辅助技术运行时,辅助技术的声音、语速和音高优先生效。
- 没有辅助技术运行时,系统继续使用 Spoken Content 设置或 utterance 上显式设置的属性。
- AAC 应用可能需要用户自定义声音,这类场景要按产品目标评估是否开启该属性。
为语音中心型应用定制声音
(05:42)AAC 应用可能会让用户选择代表自己的声音。AVSpeechUtterance 支持按语言代码或 voice identifier 指定 voice,也可以读取系统已安装 voice 列表。讲者还说明,Siri voices 即使能在 Spoken Content 设置中选择,也不能通过 AVSpeechSynthesizer API 直接使用;系统会回退到语言代码匹配的 voice。
let utterance = AVSpeechUtterance(string: "Hello World")
// Choose a voice using a language code
utterance.voice = AVSpeechSynthesisVoice(language: "en-US")
// Choose a voice using an identifier
utterance.voice = AVSpeechSynthesisVoice(identifier: AVSpeechSynthesisVoiceIdentifierAlex)
// Get a list of installed voices
let voices = AVSpeechSynthesisVoice.speechVoices()
关键点:
AVSpeechSynthesisVoice(language:)适合按语言选择系统 voice。AVSpeechSynthesisVoice(identifier:)适合指定某个已知 voice。AVSpeechSynthesisVoice.speechVoices()返回系统当前可用 voice,用户下载新 voice 后列表会更新。- Siri voices 不属于这个 API 可直接选择的范围。
调整语速、音高和音量
(06:16)如果应用决定自己控制语音风格,可以设置 utterance 的 rate、pitch multiplier 和 volume。Transcript 给出的范围分别是 rate 0 到 1、pitch multiplier 0.5 到 2、volume 0 到 1。
let utterance = AVSpeechUtterance(string: "Hello World")
// Choose a rate between 0 and 1, 0.5 is the default rate
utterance.rate = 0.75
// Choose a pitch multiplier between 0.5 and 2, 1 is the default multiplier
utterance.pitchMultiplier = 1.5
// Choose a volume between 0 and 1, 1 is the default value
utterance.volume = 0.5
关键点:
rate控制朗读速度,示例把默认 0.5 提高到 0.75。pitchMultiplier控制音高倍率,默认是 1。volume控制这次 utterance 的音量,默认是 1。- 如果同时开启
prefersAssistiveTechnologySettings且辅助技术正在运行,辅助技术设置会优先生效。
把合成语音送入正在进行的通话
(06:34)AAC 应用的一个关键场景是让非语言用户通过电话或 FaceTime 沟通。mixToTelephonyUplink 为这个场景设计:有活动中的 outgoing call 时,speech 会路由到通话;没有活动通话时,speech 走默认 audio route。
self.synthesizer = AVSpeechSynthesizer()
self.synthesizer.mixToTelephonyUplink = true
关键点:
mixToTelephonyUplink设置在AVSpeechSynthesizer上。- 活动通话可以是 phone call 或 FaceTime call。
- 没有通话时,系统不会强行改变默认播报路径。
让系统管理 speech audio session
(07:02)默认情况下,speech audio 使用应用共享的 audio session。把 usesApplicationAudioSession 设为 false 后,系统会接管 speech audio 的管理,处理 audio interruptions、设置 session active/inactive,并让 speech 与应用其他音频 duck and mix。
self.synthesizer = AVSpeechSynthesizer()
self.synthesizer.usesApplicationAudioSession = false
关键点:
usesApplicationAudioSession默认是true。- 设为
false后,speech audio 不再使用应用共享 audio session。 - 系统会管理中断处理和 session 激活状态。
- 对同时播放音乐、视频、音效的应用,这能减少 speech 与其他音频互相干扰。
核心启发
- 为取景器类工具加入可控对象播报
做什么:在识物、导览或扫描类 App 中,用 AVSpeechSynthesizer 朗读取景器识别到的对象或环境变化。
为什么值得做:Session 用 Seeing AI 说明,面向盲人或低视力用户的应用可以保持 VoiceOver 可访问,同时用 synthesizer 控制对象描述的时机。
怎么开始:先保证 UI 元素有正确的 accessibility label;对象识别结果进入稳定状态后创建 AVSpeechUtterance;如果 VoiceOver 正在运行,将 prefersAssistiveTechnologySettings 设为 true。
- 给 AAC 应用增加电话沟通模式
做什么:让用户点选短语后,把合成语音送入正在进行的电话或 FaceTime。
为什么值得做:Transcript 明确指出 mixToTelephonyUplink 可以把 speech route 到 active outgoing call,这对非语言用户很关键。
怎么开始:复用现有短语构建 UI;初始化 AVSpeechSynthesizer;进入通话模式时设置 mixToTelephonyUplink = true;没有通话时保留普通外放路径。
- 为 VoiceOver 用户提供一致的应用内播报
做什么:在需要应用自己播报的功能里,让 speech 采用当前辅助技术的声音、语速和音高。
为什么值得做:Session 演示了默认 speech 与 VoiceOver 设置不一致时的割裂感;prefersAssistiveTechnologySettings 能让第二段播报贴近 VoiceOver。
怎么开始:检查每个 AVSpeechUtterance 创建点;对面向辅助技术用户的 utterance 设置 prefersAssistiveTechnologySettings = true;对用户明确自定义 voice 的 AAC 场景保留单独设置。
- 把应用内语音从主 audio session 中拆出去
做什么:在音乐、视频或音效较多的 App 中,让 speech audio 交给系统管理,减少音频焦点冲突。
为什么值得做:usesApplicationAudioSession = false 后,系统会处理 speech audio 的中断、active 状态,并让 speech 与其他应用音频 duck and mix。
怎么开始:梳理 App 里所有 speech 出口;先在非录音场景试点设置 usesApplicationAudioSession = false;用音乐播放、视频播放、来电中断等路径做回归测试。
关联 Session
- VoiceOver efficiency with custom rotors — 同样围绕 VoiceOver 用户体验,讲如何用自定义 Rotor 提升复杂界面的导航效率。
- App accessibility for Switch Control — 讲 Switch Control 如何复用无障碍信息,适合和本 session 的 UIAccessibility 边界一起看。
- Make your app visually accessible — 从视觉可访问性补齐语音体验之外的界面适配工作。
- Accessibility design for Mac Catalyst — 关注 Mac Catalyst 中键盘、分组和 Accessibility Inspector 等跨平台无障碍细节。
- Evaluate and optimize voice interaction for your app — 从 Siri 和对话式交互角度,补充语音入口的设计评估方法。
评论
GitHub Issues · utterances