AVSpeechSynthesizer.write方法标记回调未触发,如何解决?
解决AVSpeechSynthesizer write方法标记回调不触发的问题
核心原因:你使用的普通文本字符串AVSpeechUtterance默认不会生成任何语音标记,标记回调仅在合成器处理包含显式语音标记的话语时才会触发。
具体修正步骤
- 使用带语音标记的
NSAttributedString创建话语,添加如AVSpeechSynthesisBoundaryMarkerAttribute这类标记属性; - 或使用iOS 13+支持的SSML格式字符串,通过
AVSpeechUtterance(ssmlString:)初始化话语。
示例代码(带边界标记)
import AVFoundation var synthesizer = AVSpeechSynthesizer() synthesizer.mixToTelephonyUplink = false synthesizer.usesApplicationAudioSession = false // 创建带边界标记的富文本 let attributedString = NSMutableAttributedString(string: "Hello world") // 在"Hello"结尾位置添加边界标记 attributedString.addAttribute(.AVSpeechSynthesisBoundaryMarkerAttribute, value: "hello_end", range: NSRange(location: 5, length: 0)) let utterance = AVSpeechUtterance(attributedString: attributedString) utterance.voice = AVSpeechSynthesisVoice(language: "en-US") synthesizer.write(utterance, toBufferCallback: { buffer in if let buffer = buffer as? AVAudioPCMBuffer { print("write \(buffer.frameCapacity > 1)") } else { print("could not create buffer or buffer empty") } }, toMarkerCallback: { markers in print("markers received: \(markers)") })
示例代码(SSML格式,iOS 13+)
import AVFoundation var synthesizer = AVSpeechSynthesizer() synthesizer.mixToTelephonyUplink = false synthesizer.usesApplicationAudioSession = false // SSML中添加自定义标记 let ssmlString = """ <speak> Hello <mark name="hello_end"/> world </speak> """ let utterance = try! AVSpeechUtterance(ssmlString: ssmlString) utterance.voice = AVSpeechSynthesisVoice(language: "en-US") synthesizer.write(utterance, toBufferCallback: { buffer in if let buffer = buffer as? AVAudioPCMBuffer { print("write \(buffer.frameCapacity > 1)") } else { print("could not create buffer or buffer empty") } }, toMarkerCallback: { markers in print("markers received: \(markers)") })
额外注意事项
- 确保使用的语音合成器语言与话语语言匹配,部分语音包可能不支持标记输出;
- 标记回调的触发时机对应合成到标记位置的时刻,若话语中无任何标记,回调永远不会执行。
内容的提问来源于stack exchange,提问作者Matt Bierner
相关产品推荐
相关产品推荐

