You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级macOS Ventura后pyttsx3获取语音列表报KeyError: 'VoiceAge'求助

macOS Ventura下pyttsx3获取语音列表触发KeyError: 'VoiceAge'的解决方案

问题背景

原代码在macOS Monterey + Python 3.11环境运行正常,升级至macOS Ventura后,执行engine.getProperty('voices')时出现KeyError: 'VoiceAge'错误,精简代码可复现问题:

import pyttsx3
engine = pyttsx3.init('nsss')
voices = engine.getProperty('voices')

报错信息

File "./voice assistant/tts.py", line 18, in <module>
    voices = engine.getProperty('voices')
  File "./voice assistant/venv/lib/python3.10/site-packages/pyttsx3/engine.py", line 146, in getProperty
    return self.proxy.getProperty(name)
  File "./voice assistant/venv/lib/python3.10/site-packages/pyttsx3/driver.py", line 173, in getProperty
    return self._driver.getProperty(name)
  File "./voice assistant/venv/lib/python3.10/site-packages/pyttsx3/drivers/nsss.py", line 69, in getProperty
    return [self._toVoice(NSSpeechSynthesizer.attributesForVoice_(v))
  File "./voice assistant/venv/lib/python3.10/site-packages/pyttsx3/drivers/nsss.py", line 69, in <listcomp>
    return [self._toVoice(NSSpeechSynthesizer.attributesForVoice_(v))
  File "./voice assistant/venv/lib/python3.10/site-packages/pyttsx3/drivers/nsss.py", line 64, in _toVoice
    attr['VoiceAge'])
  File "./voice assistant/venv/lib/python3.10/site-packages/objc/_convenience_mapping.py", line 18, in __getitem__objectForKey_
    return container_unwrap(res, KeyError, key)
  File "./voice assistant/venv/lib/python3.10/site-packages/objc/_convenience.py", line 122, in container_unwrap
    raise exc_type(*exc_args)
KeyError: 'VoiceAge'

已尝试无效操作

  • 重装pyttsx3
  • 使用sudo运行代码
  • 改用pyttsx3.init('dummy')初始化(无报错但无法发声)

解决方案

方案1:修改pyttsx3的nsss驱动文件

错误原因是macOS Ventura中部分系统语音的属性不再包含VoiceAge字段,而pyttsx3的nsss驱动直接通过键取值导致报错。修改驱动文件处理缺失字段:

  1. 找到虚拟环境中nsss.py的路径:./voice assistant/venv/lib/python3.10/site-packages/pyttsx3/drivers/nsss.py
  2. 打开文件,找到_toVoice函数(约60行处)
  3. 将原代码中直接取值的部分改为用get方法设置默认值:
    原代码:
return Voice(
    id=attr['VoiceIdentifier'],
    name=attr['VoiceName'],
    languages=attr['VoiceLanguages'],
    gender=attr['VoiceGender'],
    age=attr['VoiceAge'])

修改为:

return Voice(
    id=attr['VoiceIdentifier'],
    name=attr['VoiceName'],
    languages=attr['VoiceLanguages'],
    gender=attr.get('VoiceGender', 'VoiceGenderNeutral'),
    age=attr.get('VoiceAge', 0))
  1. 保存文件后重新运行代码即可正常获取语音列表。

方案2:改用原生NSSpeechSynthesizer接口(推荐)

绕过pyttsx3的兼容性问题,直接通过pyobjc调用macOS原生语音合成接口:

  1. 安装依赖:
pip install pyobjc
  1. 替代代码示例(支持选择指定语音):
from Foundation import NSSpeechSynthesizer

def va_speak(phrase, voice_id=None):
    if voice_id:
        synth = NSSpeechSynthesizer.alloc().initWithVoice_(voice_id)
    else:
        synth = NSSpeechSynthesizer.alloc().init()
    # 设置语速(范围100-300,默认175)
    synth.setRate_(150)
    # 设置音量(范围0-1,默认1)
    synth.setVolume_(1.0)
    synth.startSpeakingString_(phrase)
    while synth.isSpeaking():
        pass

# 获取所有可用语音并筛选en_US男性语音
voices = NSSpeechSynthesizer.availableVoices()
target_voice = None
for voice in voices:
    attrs = NSSpeechSynthesizer.attributesForVoice_(voice)
    if attrs.get('VoiceLanguages') == ['en_US'] and attrs.get('VoiceGender') == 'VoiceGenderMale':
        target_voice = voice
        break

# 使用指定语音发声
va_speak("Hello there", target_voice)

内容的提问来源于stack exchange,提问作者Simple_Mac User

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 00:35:20