「AVAsset」を作成し、非同期にロードしてみます。準備が整った、失敗したなどのようなプレーヤーの状態を観察し、それに基づいて再生を開始します。
func initializePlayer() {
//audio session for handling interuptions - Done Appdelegate
/*
1. Create Asset (Asset represent a single media), AVAsset -> AVAssetTrack
2. Resource properties like metadata, duration etc are loaded from asset, but if taken syncrn will block so use async
*/
let audioPath = Bundle.main.path(forResource: "big_buck_bunny", ofType: "mp4")
let resourceUrl = URL(fileURLWithPath: audioPath!)
let asset = AVAsset(url: resourceUrl)
let playableKey = "playable"
// addObserver(self, forKeyPath: #keyPath(AVPlayerItem.rate), options: [.new, .initial], context: &audioPlayerInterfaceViewControllerKVOContext)
// addObserver(self, forKeyPath: #keyPath(AVPlayerItem.status), options: [.new, .initial], context: &audioPlayerInterfaceViewControllerKVOContext)
// Load the "playable" property
asset.loadValuesAsynchronously(forKeys: [playableKey]) { [unowned self] in
var error: NSError? = nil
let status = asset.statusOfValue(forKey: playableKey, error: &error)
switch status {
case .loaded:
debugPrint("Sucessfuly loaded")
self.playerItem = AVPlayerItem(asset: asset)
self.playerItem?.addObserver(self, forKeyPath: #keyPath(AVPlayerItem.status), options: [.old, .new], context: &audioPlayerInterfaceViewControllerKVOContext)
self.playerItem?.addObserver(self, forKeyPath: #keyPath(AVPlayerItem.duration), options: [.new, .initial], context: &audioPlayerInterfaceViewControllerKVOContext)
self.player = AVPlayer(playerItem: self.playerItem)
self.player.addObserver(self, forKeyPath: #keyPath(AVPlayer.rate), options: [.new,.initial], context: &audioPlayerInterfaceViewControllerKVOContext)
let interval = CMTimeMake(1, 1)
// self.player.volume = 0.5
self.timeObserveToken = self.player.addPeriodicTimeObserver(forInterval: interval, queue: DispatchQueue.main) { [unowned self] time in
let timeElapsed = Float(CMTimeGetSeconds(time))
UIView.animate(withDuration: 1.5, animations: {
if self.userActionEnabled {
self.durationSlider.setValue(Float(timeElapsed), animated: true)
}
})
if self.userActionEnabled {
self.startTimeLabel.text = self.createTimeString(time: timeElapsed)
}
}
break
// Sucessfully loaded. Continue processing.
case .failed:
self.showErrorAlert(errorString: "Failed to load")
debugPrint("failed")
break
// Handle error
case .cancelled:
self.showErrorAlert(errorString: "Failed to load")
debugPrint("Cancelled")
break
// Terminate processing
default:
debugPrint("Error occured")
self.showErrorAlert(errorString: "Failed to load")
break
// Handle all other cases
}
}
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
guard context == &audioPlayerInterfaceViewControllerKVOContext else {
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
return
}
if keyPath == #keyPath(AVPlayerItem.status) {
let status: AVPlayerItemStatus
if let statusNumber = change?[.newKey] as? NSNumber {
status = AVPlayerItemStatus(rawValue: statusNumber.intValue)!
} else {
status = .unknown
}
// Switch over status value
switch status {
case .readyToPlay:
player.play()
break
// Player item is ready to play.
case .failed:
showErrorAlert(errorString: "Failed to load")
break
// Player item failed. See error.
case .unknown:
showErrorAlert(errorString: "Failed to load")
break
// Player item is not yet ready.
}
}
if keyPath == #keyPath(AVPlayerItem.duration) {
let newDuration: CMTime
if let newDurationAsValue = change?[NSKeyValueChangeKey.newKey] as? NSValue {
newDuration = newDurationAsValue.timeValue
}
else {
newDuration = kCMTimeZero
}
let hasValidDuration = newDuration.isNumeric && newDuration.value != 0
let newDurationSeconds = hasValidDuration ? CMTimeGetSeconds(newDuration) : 0.0
let currentTime = hasValidDuration ? Float(CMTimeGetSeconds((player.currentTime()))) : 0.0
durationSlider.maximumValue = Float(newDurationSeconds)
durationSlider.value = currentTime
nextBtn.isEnabled = hasValidDuration
playPauseBtn.isEnabled = hasValidDuration
previousBtn.isEnabled = hasValidDuration
durationSlider.isEnabled = hasValidDuration
startTimeLabel.isEnabled = hasValidDuration
startTimeLabel.text = createTimeString(time: currentTime)
endTimeLabel.isEnabled = hasValidDuration
endTimeLabel.text = createTimeString(time: Float(newDurationSeconds))
}
if keyPath == #keyPath(AVPlayer.rate) {
// Update `playPauseButton` image.
let newRate = (change?[NSKeyValueChangeKey.newKey] as? NSNumber)?.doubleValue
let buttonImageName = newRate == 1.0 ? "Pause" : "Play"
let buttonImage = UIImage(named: buttonImageName)
playPauseBtn.setImage(buttonImage, for: UIControlState())
}
}
問題は、audioPathを記述したときに型を宣言できるということです。しかし、私はURLでそれを行うことはできません。あなたのコードの外に私は複雑すぎる、私は把握することはできません。 –