首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

iOS AVPlayer 獲取影音總時長:使用 currentItem.duration

     編輯:程式設計綜合問答

問題現象

需取得 AVPlayer 播放線上音樂的總時長,嘗試直接存取 player.duration 失敗。

正確屬性

AVPlayer 本身無 duration 屬性,時長資訊在 AVPlayerItem 中:


// 正確取得時長 (CMTime)
CMTime duration = player.currentItem.duration;
// 或
CMTime duration = player.currentItem.asset.duration;

完整使用範例


// 1. 建立 Player
AVPlayer *player = [AVPlayer playerWithURL:url];
self.player = player;

// 2. 監聽狀態就緒 (非同步載入)
[player.currentItem addObserver:self forKeyPath:@"status" options:0 context:nil];

// 3. KVO 回調中取得時長
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([keyPath isEqualToString:@"status"] && player.currentItem.status == AVPlayerItemStatusReadyToPlay) {
        CMTime duration = player.currentItem.duration;
        if (CMTIME_IS_VALID(duration) && !CMTIME_IS_INDEFINITE(duration)) {
            double seconds = CMTimeGetSeconds(duration);
            // 格式化顯示
            NSString *timeStr = [NSString stringWithFormat:@"%02d:%02d", 
                (int)seconds / 60, (int)seconds % 60];
            self.durationLabel.text = timeStr;
        }
    }
}

// 4. 移除觀察者 (dealloc/viewDidDisappear)
[player.currentItem removeObserver:self forKeyPath:@"status"];

現代 Swift + Combine 寫法


@Published var durationText: String = "--:--"

func loadPlayer(url: URL) {
    let player = AVPlayer(url: url)
    self.player = player
    
    // 使用 Publisher 監聽 status
    player.currentItem.publisher(for: \.status)
        .compactMap { $0 }
        .filter { $0 == .readyToPlay }
        .map { _ in player.currentItem.duration }
        .filter { $0.isValid && !$0.isIndefinite }
        .map { CMTimeGetSeconds($0) }
        .map { seconds in
            String(format: "%02d:%02d", Int(seconds) / 60, Int(seconds) % 60)
        }
        .assign(to: &$durationText)
}

關鍵注意點

  1. 非同步載入:AVPlayerItem 載入元資料需時間,必須等 status == ReadyToPlay 才能讀取有效時長。
  2. 檢查 CMTime 有效性:CMTIME_IS_VALID 且 !CMTIME_IS_INDEFINITE(直播流無確定時長)。
  3. 秒數轉換:CMTimeGetSeconds(duration) 回傳 Double,精確到毫秒。
  4. 記憶體管理:及時移除 KVO 觀察者,避免崩潰。

常見誤區

  • player.duration:不存在此屬性。
  • player.currentItem.duration 在 status != ReadyToPlay 時為 kCMTimeInvalid 或 indefinite。
  • 直播流(HLS/Live)無固定時長,duration 為 indefinite,需顯示「直播中」而非時間。

掌握 AVPlayerItem 狀態機制與 CMTime 操作,是 iOS 影音播放開發的核心基本功。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved