利用 AVSpeechSynthesizer 講話
前期提要:
利用 AVSpeechSynthesizer 講話
首先要import 才能使用AVSpeechSynthesizer這個函示庫
import AVFoundation
再來把元件連結Storyboard
@IBOutlet weak var speakTextfield: UITextField!@IBOutlet weak var speakSpeed: UISlider!@IBOutlet weak var speakRate: UISlider!@IBOutlet weak var speakHistoryTableView: UITableView!@IBOutlet weak var speakPlayButton: UIButton!
因為有加入歷史資料功能,所以有UITableView。
宣告變數(兩個內建語音合聲器與發聲器以及預設歷史資料)
var speakUtterance = AVSpeechUtterance()var speakSynthesizer = AVSpeechSynthesizer()var speakHistory : [SpeakHistory] = [SpeakHistory(speakText: "I Love Swift", speakRate: 1.0, speakSpeed: 1.0)]
我們在viewDidLoad畫面跑完的時候修改預設值,並委託TableView的delegate以及dataSource和AVSpeechSynthesizer的delegate給ViewController
speakRate.minimumValue = 0.5speakRate.maximumValue = 2.0speakRate.value = 1.0// [0.5 - 2] Default = 1speakSpeed.minimumValue = 0.0speakSpeed.maximumValue = 1.0speakSpeed.value = 1.0// [0-1] Default = 1self.speakHistoryTableView.delegate = selfself.speakHistoryTableView.dataSource = selfself.speakSynthesizer.delegate = self
建立語音的類別
class SpeakHistory{var speakText: Stringvar speakRate: Floatvar speakSpeed: Floatinit(speakText: String, speakRate: Float, speakSpeed: Float) {self.speakText = speakTextself.speakRate = speakRateself.speakSpeed = speakSpeed}}
Xcode 14的新功能不用打init直接幫我們建立好,真的很棒!!
播放程式碼:
if(speakSynthesizer.isPaused){speakSynthesizer.continueSpeaking()}else if(speakSynthesizer.isSpeaking){speakSynthesizer.pauseSpeaking(at: AVSpeechBoundary.immediate)}else{if let speakText = speakTextfield.text, !speakText.isEmpty{speakUtterance = AVSpeechUtterance(string: speakText)speakUtterance.pitchMultiplier = speakRate.valuespeakUtterance.rate = speakRate.valuespeakUtterance.voice = AVSpeechSynthesisVoice(language: "zh-TW")speakSynthesizer.speak(speakUtterance)speakHistory.insert(SpeakHistory(speakText: speakText, speakRate: speakRate.value, speakSpeed: speakSpeed.value),at: 0)speakHistoryTableView.reloadData()}}
這裡有判斷speakSynthesizer是否為暫停、播放中,沒有的話就播放新內容,並且抓Slider的Value(包含語速及語調),當speakSynthesizer播放就新增一筆資料在TableView的頂端使用
陣列.insert(你的資料,at: 陣列的第幾個位置)
speakHistory.insert(SpeakHistory(speakText: speakText, speakRate: speakRate.value, speakSpeed: speakSpeed.value),at: 0)
TableView 回傳有幾個Cell,我們回傳陣列的數量
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {return speakHistory.count}
TableView的資料處理,把speakHistory[第幾筆資料]帶進去cell
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {guard let cell = speakHistoryTableView.dequeueReusableCell(withIdentifier: "speakHistoryCell", for: indexPath) as? SpeakTableViewCell else {return UITableViewCell()}cell.speakText.text = speakHistory[indexPath.row].speakTextcell.speakRate.text = "\(speakHistory[indexPath.row].speakRate)"cell.speakSpeed.text = "\(speakHistory[indexPath.row].speakSpeed)"print("init cell")return cell}
如果點擊Cell,資料會帶入Slider以及Textfield
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {let speak = speakHistory[indexPath.row]speakTextfield.text = speak.speakTextspeakRate.value = speak.speakRatespeakSpeed.value = speak.speakSpeed}
如果向左滑,並點擊刪除
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {if(editingStyle == .delete){speakHistory.remove(at: indexPath.row)speakHistoryTableView.reloadData()}}
輸入AVSpeechSynthesizerDelegate並點選Jump to Definition
或者在 官網文件找到 AVSpeechSynthesizerDelegate
在這裡我們可以看到AVSpeechSynthesizer 開放的Protocol,我們就可以委託ViewController 幫我們監聽 speechSynthesizer的delegate
self.speakSynthesizer.delegate = self
透過委託的方式幫我們更改播放按鈕的Title
delegate程式碼
func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {self.speakPlayButton.setTitle("播放", for: .normal)}func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didStart utterance: AVSpeechUtterance) {self.speakPlayButton.setTitle("暫停", for: .normal)}func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didPause utterance: AVSpeechUtterance) {self.speakPlayButton.setTitle("繼續播放", for: .normal)}func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didContinue utterance: AVSpeechUtterance) {self.speakPlayButton.setTitle("暫停", for: .normal)}
Github: