🐈
AVPlayerのdurationの取得
AVPlayerのdurationの取得
解決策
AVPlayerからではなく、AVAssetからdurationを取得する。
# これで正しい値が取得できました。
let asset = AVURLAsset(url: validURL, options: [AVURLAssetPreferPreciseDurationAndTimingKey: true])
let assetDuration = try await CMTimeGetSeconds(asset.load(.duration))
print ("asset duration :", assetDuration)
これでも1秒2秒の誤差があるものの、使える程度の値が取得できました。
private var player = AVPlayer()
var duration: TimeInterval {
guard let playerItem = player.currentItem, playerItem.status == .readyToPlay else {
return 0.0
}
return CMTimeGetSeconds(playerItem.duration)
}
もしくは、これでも誤差がありますが取得できました。
(これだとduplicatedしているという警告が出ます。)
private var player = AVPlayer()
var duration: TimeInterval {
guard let playerItem = player.currentItem, playerItem.status == .readyToPlay else {
return 0.0
}
return CMTimeGetSeconds(playerItem.asset.duration)
}
背景と試したこと
AVPlayerでmp3のdurationを取得したかったのですが、
以下のコードではdurationの値が大きくなったり小さくなったりして正しく取得できませんでした。
# 試したコード1
do {
if let currentItem = self.audioPlayer?.currentItem {
let durationSeconds = try await CMTimeGetSeconds(currentItem.asset.load(.duration))
print ("durationSeconds :", durationSeconds)
}
} catch {
print("Error: \(error)")
}
# 試したコード2
# 読み込みのタイミング関連しているかもしれないと思い以下のコードを試しましたが同じ結果でした。
func loadDuration(of url: URL) async {
let asset = AVAsset(url: url)
// Create an array containing the asset keys we need to be loaded
let keys = ["duration"]
await withCheckedContinuation { continuation in
// Load the asset's keys asynchronously
asset.loadValuesAsynchronously(forKeys: keys) {
// The keys are loaded, now access the duration
var error: NSError?
let status = asset.statusOfValue(forKey: "duration", error: &error)
if status == .loaded {
let duration = asset.duration
let durationSeconds = CMTimeGetSeconds(duration)
DispatchQueue.main.async {
print("Duration seconds:", self.timeString(time: durationSeconds))
continuation.resume()
}
} else if status == .failed {
print("Failed to load duration with error: \(String(describing: error))")
continuation.resume(throwing: (error ?? NSError(domain: "AVAssetDurationError", code: 0, userInfo: nil)) as! Never)
} else {
print("Duration not available yet.")
continuation.resume()
}
}
}
}
環境
Xcode Version 15.2
Discussion