Xcode配置
- 如果需要后台播报语音,需要到Target->Capabilities选中Background Modes 的 Audio...选项。
若不勾选此项,程序在后台运行的时候调用语音播报会报出codeCannotStartPlaying错误。
管理类文件
import AVFoundation
class SpeechUtteranceManager: NSObject {
/// 单例管理语音播报 比较适用于多种类型语音播报管理
public static let shared = SpeechUtteranceManager()
var synthesizer = AVSpeechSynthesizer()
var speechUtterance: AVSpeechUtterance?
var voiceType = AVSpeechSynthesisVoice(language: Locale.current.languageCode)
private override init() {
super.init()
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, with: .duckOthers)
} catch {
print(error.localizedDescription)
}
synthesizer.delegate = self
}
/// 自定义语音播报方法
/// 此处只举例播报一个String的情况
func speechWeather(with weather: String) {
if let _ = speechUtterance {
synthesizer.stopSpeaking(at: .immediate)
}
do {
try AVAudioSession.sharedInstance().setActive(true)
} catch {
print(error.localizedDescription)
}
speechUtterance = AVSpeechUtterance(string: weather)
speechUtterance?.voice = voiceType
speechUtterance?.rate = 0.5
synthesizer.speak(speechUtterance!)
}
}
extension SpeechUtteranceManager: AVSpeechSynthesizerDelegate {
func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
do {
try AVAudioSession.sharedInstance().setActive(false, with: .notifyOthersOnDeactivation)
} catch {
print(error.localizedDescription)
}
speechUtterance = nil
}
}
使用
/// 例如播报天气
/// 若要兼容语言国际化
/// NSLocalizedString 搭配 Locale.current.languageCode 食用效果更佳
SpeechUtteranceManager.shared.speechWeather(with: NSLocalizedString("The Rainy Day", comment: ""))
关键代码
setCategory
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, with: .duckOthers)
} catch {
print(error.localizedDescription)
}
- AVAudioSessionCategoryPlayback:后台播报
- .duckOthers:混合通道,语音播报时其他软件声音变小(音乐)
若不设置混合通道,在后台播报时会报codeCannotInterruptOthers错误
setActive
将 AVAudioSession 置为活动状态
do {
try AVAudioSession.sharedInstance().setActive(true)
} catch {
print(error.localizedDescription)
}
记得在结束调用时将活动状态置为false
do {
try AVAudioSession.sharedInstance().setActive(false)
} catch {
print(error.localizedDescription)
}
网友评论
enum AVAudioSessionInterruptionType:
case began /* the system has interrupted your audio session */
case ended /* the interruption has ended */