利用 AVPlayer 播放音樂音效
彼得潘的生活不能沒有音樂,尤其是在寫 code 的時候。因此接下來就讓我們認識既能播放 App 裡的歌曲,也能播放網路上歌曲的音樂播放器, AVPlayer ! (ps: 其實不只音樂,它也能播放影片。)
將音樂檔加到 Xcode 專案
利用 AVPlayer 播放 App 裡的音樂
以下範例分別示範在 SwiftUI & UIKit App 畫面出現時播放音樂。
SwiftUI 版本
import SwiftUI
import AVFoundation
struct ContentView: View {
@State private var player = AVPlayer()
var body: some View {
Text("原來你是我最想留住的幸運")
.onAppear {
let url = Bundle.main.url(forResource: "黑色毛衣", withExtension: "mp3")!
let playerItem = AVPlayerItem(url: url)
player.replaceCurrentItem(with: playerItem)
player.play()
}
}
}
UIKit 版本
import UIKit
import AVFoundation
class ViewController: UIViewController {
let player = AVPlayer()
override func viewDidLoad() {
super.viewDidLoad()
let url = Bundle.main.url(forResource: "黑色毛衣", withExtension: "mp3")!
let playerItem = AVPlayerItem(url: url)
player.replaceCurrentItem(with: playerItem)
player.play()
}
}
說明:
- 加入 AVFoundation 函式庫(framework)
import AVFoundation
為了使用 AVPlayer 播放音樂,必須先加入 AVFoundation。
- 宣告 AVPlayer 型別的 property player。
SwiftUI 的寫法。
@State private var player = AVPlayer()
UIKit 的寫法。
let player = AVPlayer()
生成播放音樂的 AVPlayer 物件。
- 設定 player 播放的音樂並開始播放。
let url = Bundle.main.url(forResource: "黑色毛衣", withExtension: "mp3")!
let playerItem = AVPlayerItem(url: url)
player.replaceCurrentItem(with: playerItem)
player.play()
(1) 產生音樂在 App 裡路徑的 URL。
let url = Bundle.main.url(forResource: "music", withExtension: "mp3")!
利用 Bundle.man 取得 App 主要的 Bundle,也就是 App 本身的資料夾。放在 Project navigator 下的 music.mp4 將在 App 的資料夾下,透過呼叫 function url(forResource:withExtension:) 可取得它在資料夾裡的 URL,參數 forResource 傳入檔名,參數 withExtension 傳入附檔名。
func url(forResource name: String?, withExtension ext: String?) -> URL?
值得注意的,function url 回傳的 URL 將是 optional ,因此我們加上 ! 取值。假設我們不會手殘,檔名不會打錯,因此我們可以放心加上 !。
(2) 利用 AVPlayerItem 生成要播放的音樂。
let playerItem = AVPlayerItem(url: fileUrl)
(3) 設定 player 要播放的 AVPlayerItem。
player.replaceCurrentItem(with: playerItem)
(4) 開始播放音樂。
player.play()
現在 App 啟動後,將可立即聽到美妙的音樂。
也許有人有疑問,為何不在 SwiftUI 範例的 onAppear 或 UIKit 範例的 viewDidLoad 裡產生 AVPlayer 物件,而是另外宣告 property 儲存呢 ? 比方以下我們在 function onAppear 裡宣告常數 player。
struct ContentView: View {
var body: some View {
Text("Hello, World!")
.onAppear {
let player = AVPlayer()
let url = Bundle.main.url(forResource: "黑色毛衣", withExtension: "mp3")!
let playerItem = AVPlayerItem(url: url)
player.replaceCurrentItem(with: playerItem)
player.play()
}
}
}
剛剛的程式還是可以執行,但我們完全聽不到音樂,因為常數 player 是在 onAppear 的 { } 裡生成,所以 onAppear 執行完後,player 就會被殘忍地結束生命,它連一秒鐘的音樂都來不及唱出。
利用 AVPlayer 播放網路上的音樂
我們也可以用 AVPlayer 播放網路上的音樂,只要在生成 AVPlayerItem 時傳入網路上音樂的 URL,比方以下例子:
let url = URL(string: "https://audio-ssl.itunes.apple.com/apple-assets-us-std-000001/AudioPreview118/v4/69/0e/98/690e98db-440d-cb0c-2bff-91b00a05bdda/mzaf_1674062311671795807.plus.aac.p.m4a")!
let playerItem = AVPlayerItem(url: url)
暫停音樂
呼叫 function pause。
player.pause()
調整音量
volum 的大小是 0 ~ 1。
player.volume = 0.8
volume 控制的音量是相對於系統的音量,如下圖所示,倘若此時系統的音量是一半的音量,那麼就算 volume 等於 1 也會只有一半的音量。
如果想要調整系統的音量,可直接在畫面上加入 MPVolumeView。加入前記得先 import MediaPlayer,然後請在實機測試,因為它無法在模擬器測試。
let volumeView = MPVolumeView(frame: CGRect(x: 10, y: 100, width: 300, height: 40))
view.addSubview(volumeView)
播放下一首 / 上一首歌
AVPlayer 播放的音樂由 AVPlayerItem 控制,因此我們只要呼叫 function replaceCurrentItem(with:),傳入下一首,上一首歌的 URL,即可改變播放的音樂。
比方下一首歌是周興哲的你好不好,播放的程式如下:
let url = Bundle.main.url(forResource: "你好不好", withExtension: "mp4")!
let playerItem = AVPlayerItem(url: url)
player.replaceCurrentItem(with: playerItem)
判斷目前是否正在播放歌曲
if player.timeControlStatus == .playing {
}
取得歌曲目前播放到第幾秒
player.currentTime().seconds
取得目前播放歌曲的長度
player.currentItem?.duration
調整歌曲播放的區段(SEEK)
利用 seek 控制歌曲播放的區段。
從頭播放。
player.seek(to: .zero)
從第 30 秒開始播放。
let time = CMTime(value: 30, timescale: 1)
player.seek(to: time)
timeScale 通常會傳 1,value / timescale 表示秒數,因此 CMTime(value: 30, timescale: 2) 將變成第 15 秒。
歌曲播放完的通知,AVPlayerItemDidPlayToEndTime
很多時候我們想知道歌曲播完了,比方想在周興哲的你好不好唱完後,繼續播放五月天的好好。
我們可在音樂播完了收到 Notification,此時它會發送通知AVPlayerItemDidPlayToEndTime。
NotificationCenter.default.addObserver(forName: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil, queue: .main) { _ in
print("finish, next song")
}
偵測歌曲目前播放的時間
產生 AVPlayer 的多種方法
如果一開始已知道播放的歌曲,也可以在產生 AVPlayer 時傳入 playerItem 或 url。
重覆播放音樂
剛剛的程式已經可以順利播放音樂,可惜它只能播放一次。若覺得一次不夠好,想多聽幾次的朋友,可參考以下連結利用 AVPlayerLooper 實現重覆播放。