想說的話,讓機器人來替你說Speak2U

過完溫暖的Xmas,是否有和心儀的對象告白成功呢?

如果說不出口的話,就寫個app替你說吧 ^___^

首先需要運用把文字轉成語音的模組,因此導入AVFAudio的框架

UIKit是基本的

import UIKit
import AVFundation

然後先想要怎樣的畫面來呈現…

可能需要一個虛擬的角色來替你說話

正值下雪的季節,找個雪人加上機器人應該很合適

用emoji做一個新的角色

鏘鏘鏘鏘~ 新的角色誕生了

然後…

可能需要一個欄位來輸入想說的話

可以加入一些調整語速,

需要的聲音,男聲或女聲… 這裡選錯了就會告白失敗領好人卡

然後試著做出畫面

文字打好以後,按嘴巴的部分就可以說話,因此做一個透明的Button在嘴巴的範圍,把這語音功能掛在這顆Button的IBAction

使用AVFundation框架下面的AVSpeechutterance來將文字轉成語音,然後用AVSpeechSynthesisVoice來控制文字辨識的語系

只是不曉得為什麼不能在IBAction裡面將AVSpeechSynthesizer()實體化?

let synthesizer = AVSpeechSynthesizer()   //要放在外面
@IBAction func speak(_ sender: Any) {
let utterance = AVSpeechUtterance(string: speakwords.text!)
utterance.voice = AVSpeechSynthesisVoice(language: "zh-TW")
utterance.rate = speedSlider.value
utterance.pitchMultiplier = pitchSlider.value
synthesizer.speak(utterance)

加入兩個slider來控制速度和語調,因為拖曳slider改變值是做一樣的事,可以放在同一個IBAction,旁邊加上Label顯示數值,%.1f設定小數點到一位

@IBAction func sliderAdjust(_ sender: UISlider) {
let adjustment = AVSpeechUtterance()
adjustment.pitchMultiplier = pitchSlider.value
pitchValueIndicator.text = String(format: "%.1f", pitchSlider.value)
adjustment.rate = speedSlider.value
speedValueIdencator.text = String(format:"%.1f", speedSlider.value)
}

因為app執行一開始沒有更動slider值的時候,Label會收不到數值無法顯示,所以要在viewDidLoad重複這兩行,在畫面載入完成以前讀取一下slider的初始值

pitchValueIndicator.text = String(format: "%.1f", pitchSlider.value)

speedValueIdencator.text = String(format:"%.1f", speedSlider.value)

接下來遭遇鍵盤的問題,打完字收不起來,先用最簡單的方式,在畫面空白處點一下收鍵盤,需要加上這個function:

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
view.endEditing(true)
}

其次是文字輸入欄位,會被鍵盤擋住,我想要輸入時鍵盤可以往上推,找了找一些技術文件,大致上的解決方式就是用監聽鍵盤顯示和消失的兩個動作,需要在viewDidLoad加上這兩行,註冊監聽的項目:

NotificationCenter.default.addObserver(self, selector:#selector(keyboardWillShow), name:UIResponder.keyboardWillShowNotification, object: nil)

NotificationCenter.default.addObserver(self, selector:#selector(keyboardWillHide), name:UIResponder.keyboardWillHideNotification, object: nil)

然後在監聽觸發時,修改底層view的Y軸值減去鍵盤的高度

在viewDidLoad之外加上兩個@objc:

@objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y == 0 {
self.view.frame.origin.y -= keyboardSize.height
}
}
}

@objc func keyboardWillHide(notification: NSNotification) {
if ((notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue) != nil {
if self.view.frame.origin.y != 0 {
self.view.frame.origin.y = 0
}
}
}

keyboardWillShowNotification 和 keyboardWillHideNotification 都是在UIResponder內定的property,這裡定義兩個function來控制他們該做的事情,對應情況調整view.frame的範圍數值

以上

--

--