Swift中根据AVSpeechUtterance朗读内容同步调整滑块值的问题
嘿,我来帮你搞定这个滑块和朗读同步的问题~
你现在的问题在于,代码里只是在启动朗读后尝试设置了一次滑块值,但没有实时监听朗读的进度,所以滑块自然不会跟着朗读内容动态变化。要实现同步,得借助AVSpeechSynthesizer的代理方法来追踪朗读进度,然后实时更新滑块。
接下来给你一步步的实现方案:
第一步:遵循AVSpeechSynthesizerDelegate协议
让你的ViewController(或者处理朗读的类)遵循这个代理协议,这样才能接收朗读进度的回调:
class YourViewController: UIViewController, AVSpeechSynthesizerDelegate { // 你的现有属性:比如语音合成器、滑块、待朗读文本等 let synth = AVSpeechSynthesizer() @IBOutlet weak var sliderValue: UISlider! var idFileText: String = "" // 你的待朗读文本内容 }
第二步:设置代理
在viewDidLoad(或者初始化语音合成器的地方)给synth设置代理,这是接收回调的关键:
override func viewDidLoad() { super.viewDidLoad() synth.delegate = self }
第三步:修改朗读启动代码
保留你原来的朗读逻辑,但移除多余的continueSpeaking()调用(speak()方法已经会启动朗读):
func startTextToSpeech() { let myUtterance = AVSpeechUtterance(string: idFileText) myUtterance.rate = 0.3 // 保持你设置的语速 synth.speak(myUtterance) }
第四步:实现进度回调方法
这是实现同步的核心!willSpeakRangeOfSpeechString代理方法会在朗读到文本的某一段时被持续调用,我们在这里计算进度并更新滑块:
func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, willSpeakRangeOfSpeechString characterRange: NSRange, utterance: AVSpeechUtterance) { // 计算当前朗读进度比例:已读字符数 / 总字符数 let totalLength = Float(utterance.speechString.count) let currentReadLength = Float(characterRange.location + characterRange.length) let progress = currentReadLength / totalLength // 针对你的场景:如果文本是纯数字(比如"50"、"100") if let totalValue = Int(utterance.speechString) { // 把进度转换成对应的滑块值(假设滑块的max为totalValue,min为0) let targetValue = progress * Float(totalValue) self.sliderValue.setValue(targetValue, animated: true) } else { // 如果文本不是纯数字,直接用进度比例设置滑块(比如滑块范围0-1) self.sliderValue.setValue(progress, animated: true) } }
额外注意事项
- 确保滑块的
minimumValue和maximumValue设置匹配你的需求:比如文本是"100",滑块的max要设为100,同步的数值才会准确。 - 暂停/继续朗读时,代理方法会自动在继续朗读时恢复触发,不需要额外写逻辑适配。
- 如果你的文本不是纯数字(比如一段句子),可以根据需求调整进度计算方式,比如按单词拆分或者段落来对应滑块位置。
这样修改后,滑块就会跟着朗读的进度实时更新啦~
内容的提问来源于stack exchange,提问作者Anurag Mishra
相关产品推荐
相关产品推荐

