IOS13 APP『Swift5』實例說明 — 算數練習App(影音篇)

Shin Chao
9 min readDec 23, 2019

--

【 播放音樂】

播放音樂其實很簡單,一般來說有兩種方式,一種是使用AVAudioPlayer,另一種是使用AVPlayer 播放。那你可能有個疑問,這兩種都能播放音樂,那什麼時候用AVPlayer呢? 如果是播放App內的檔案,那基本上都可以,但是如果是網路上的音樂則建議使用AVPlayer。如果要使用Audio或是Video相關IOS內建的API,都需要記得import AVFoundation。

那先來說一下播放App內的檔案吧,首先當然是需要將音樂檔案加入專案內,其實只要將音樂案,直接拉到專案內的Project Navigator 裡就好,如下圖步驟1,這邊我是建立一個MusicGroup目錄專門放mp3,之後會跳出步驟2的視窗,這邊在加入檔案時要勾選 Copy items if needed,這樣才會將檔案複製一份,加入到專案的資料夾裡,不然這專案給其他人用時,會找不到這個檔案。

接下來要說的是如何取得剛剛放入專案的mp3的位置了,這就要使用Bundle.main.url了,這是利用 Bundle.main 來得到 Bundle 物件,可用來讀取專案裡的檔案,然後呼叫Bundle.main的 function url(forResource:withExtension:) 就會得到檔案路徑的 URL。

if let url = Bundle.main.url(forResource: "How_it_Began", withExtension: "mp3") {
}

這邊是用Optional Binding來取得路徑,如不了解Optional Binding,可以參考下面這篇。

有了mp3的位置,那麼就剩下如何播放了,那就來說一下AVAudioPlayer好了,其實非常簡單,就是呼叫AVAudioPlayer,將剛剛的url傳入就好,至於前面為什麼要加上try?呢?是因為有可能會有錯誤,所以AVAudioPlayer會丟出throws,因此需要加上try?。

var player: AVAudioPlayer?
if let url = Bundle.main.url(forResource: "How_it_Began", withExtension: "mp3") {
player = try? AVAudioPlayer(contentsOf: url)
player?.play()
}

如果要停止就呼叫player?.stop()就會停止播放。

這邊有一個需要注意的地方,不論是AVAudioPlayer與AVPlayer,在生成物件的時候,就是必須在Contorller內宣告,而不是在viewDidLoad()內宣告,因為如果在viewDidLoad()內宣告則會聽不到聲音的,至於為什麼呢?其實很簡單,因為在viewDidLoad()內宣告,生成的物件會隨viewDidLoad()顯示完畫面後,一起結束,例如var player: AVAudioPlayer?,連帶的player這個變數也會結束,所以你是聽不到聲音的。

var player: AVAudioPlayer?
override func viewDidLoad() {
if let url = Bundle.main.url(forResource: "How_it_Began", withExtension: "mp3") {
player = try? AVAudioPlayer(contentsOf: url)
player?.play()
}
}

而AVPlayer的用法只有在生成的物件不同,是產生AVPlayer的物件,而且不需要try?。

var player: AVPlayer?
override func viewDidLoad() {
if let url = Bundle.main.url(forResource: "How_it_Began", withExtension: "mp3") {
player = AVPlayer(url: url)
player?.play()
}
}

如果是要播網路上的音樂就將Bundle.main.url改為URL,來取得網路上的音樂位置後再使用AVPlayer播放。

var player: AVPlayer?
override func viewDidLoad() {
if let url = URL(string: "https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview128/v4/df/6f/14/df6f1423-0870-a92d-7c88-e2125696af32/mzaf_2927801479591561868.plus.aac.p.m4a") {
player = AVPlayer(url: url)
player?.play()
}
}

上面說明了播一首音樂的方式,如果需要一直循環,那就要用AVPlayerLooper來完成循環播放的功能,那就來說明一下如何循環播放吧。

重複播放單曲主要是要生成AVQueuePlayer(),然後用AVPlayerItem()生成要重複播放的音樂,最後用AVPlayerLooper()用剛剛生成的player與item,將音樂重複播放。

let repeatPlayer = AVQueuePlayer()
var looper: AVPlayerLooper?
override func viewDidLoad() {
if let url = Bundle.main.url(forResource: "How_it_Began", withExtension: "mp3") {
let item = AVPlayerItem(url: url)
looper = AVPlayerLooper(player: repeatPlayer, templateItem: item)
repeatPlayer.play()
}
}

上面簡單的說一下播放音樂的方式,其實還可以控制音樂大小聲,暫停等功能,原則上都是有支援,想了解可以看一下apple的相關說明。

【 語音播放】

語音播放就是使用內建的合成器來發出人聲,接下來就來說一下如何發出像Siri般的聲音吧。如同之前所說的,要記得如果要使用Audio或是Video相關IOS內建的API,都需要記得import AVFoundation。

Step 1 : 使用AVSpeechUtterance()將文字變成要講的話。

let speakResultUtterance = AVSpeechUtterance(string: "恭喜!答對了")

Step 2 : 設定說哪國的語言,預設是英文,可以透過AVSpeechUtterance()的屬性.voice來修改,使用AVSpeechSynthesisVoice()將語系設定為”zh-TW”中文。

speakResultUtterance.voice = AVSpeechSynthesisVoice(language: "zh-TW")

Step 3 : 接下來就是生成合成器AVSpeechSynthesizer(),這樣才能透過合成器發出聲音。

let speakResultSynthesizer = AVSpeechSynthesizer()

Step 4 : 最後就透過AVSpeechSynthesizer()的方法.speak來發出聲音了。

speakResultSynthesizer.speak(speakResultUtterance)

前面所說的只是基本的用法,其實還有其他屬性,下面說一下AVSpeechUtterance()其他的屬性。

  • .rate : 說話速度(0 ~ 1)。
  • .pitchMultiplier : 說話語調(0.5 ~ 2.0)
  • .volume : 聲音大小調整(0 ~ 1)
  • .voice : 設定語系
  • .postUtteranceDelay : 讀完一段話之後,停多久再說下一段話。
  • .preUtteranceDelay : 讀一段話之前,等多久再說。

補充一點,如果要停止說話可以使用AVSpeechSynthesizer()的方法.stopSpeaking,暫停說話可以用.pauseSpeaking。

speakResultSynthesizer.stopSpeaking(at: .immediate)speakResultSynthesizer.pauseSpeaking(at: .immediate)

--

--