如何从AVPlayer获取持续时间(不是AVAudioPlayer)?

时间:2010-10-19 20:25:36

标签: iphone objective-c xcode streaming

我想为我的AVPlayer制作一个UISlider(擦洗器)。但由于这不是AVAudioPlayer,因此它没有内置的持续时间。有关如何创建滑块以快进,快退和播放进度的任何建议?

我在AVPlayer上阅读了doc,它有一个内置的seekToTime或seekToTime:toleranceBefore:toleranceAfter:。我真的不明白。这是我滑块的答案吗? AVPlayer还有addPeriodicTimeObserverForInterval:queue:usingBlock:,这是用于获取我的音轨的持续时间吗?有人能举例说明如何实现这段代码吗?我不是Apple的文档的粉丝。这似乎很难理解。

8 个答案:

答案 0 :(得分:121)

self.player.currentItem.asset.duration

知道了!

答案 1 :(得分:35)

<强>头

#import <AVFoundation/AVPlayer.h>
#import <AVFoundation/AVPlayerItem.h>
#import <AVFoundation/AVAsset.h>

<强>码

CMTime duration = self.player.currentItem.asset.duration;
float seconds = CMTimeGetSeconds(duration);
NSLog(@"duration: %.2f", seconds);

<强>框架

AVFoundation
CoreMedia

答案 2 :(得分:11)

从iOS 4.3开始,您可以使用稍短的内容:

self.player.currentItem.duration;

答案 3 :(得分:11)

让Swift在几秒钟内获得持续时间

if let duration = player.currentItem?.asset.duration {
    let seconds = CMTimeGetSeconds(duration)
    print("Seconds :: \(seconds)")
}

答案 4 :(得分:4)

来自StitchedStreamPlayer

您应该使用player.currentItem.duration

- (CMTime)playerItemDuration
{
    AVPlayerItem *thePlayerItem = [player currentItem];
    if (thePlayerItem.status == AVPlayerItemStatusReadyToPlay)
    {        
        /* 
         NOTE:
         Because of the dynamic nature of HTTP Live Streaming Media, the best practice 
         for obtaining the duration of an AVPlayerItem object has changed in iOS 4.3. 
         Prior to iOS 4.3, you would obtain the duration of a player item by fetching 
         the value of the duration property of its associated AVAsset object. However, 
         note that for HTTP Live Streaming Media the duration of a player item during 
         any particular playback session may differ from the duration of its asset. For 
         this reason a new key-value observable duration property has been defined on 
         AVPlayerItem.

         See the AV Foundation Release Notes for iOS 4.3 for more information.
         */     

        return([playerItem duration]);
    }

    return(kCMTimeInvalid);
}

答案 5 :(得分:3)

在此示例中,avPlayer是AVPlayer实例。

我构建了一个使用以下内容的视频控件:

要定位滑块使用类似的东西来获取播放头在电影中的百分比,您需要重复触发此功能。所以我会运行像:

这样的功能
float scrubberBarLocation = (scrubberBgImageView.frame.size.width / 100.0f) * [self moviePercentage];


- (float)moviePercentage {

    CMTime t1 = [avPlayer currentTime];
    CMTime t2 = avPlayer.currentItem.asset.duration;

    float myCurrentTime = CMTimeGetSeconds(t1);
    float myDuration = CMTimeGetSeconds(t2);

    float percent = (myCurrentTime / myDuration)*100.0f;
    return percent;

}

然后更新视频我会做类似的事情:

- (void)updateVideoPercent:(float)thisPercent {

    CMTime t2 = avPlayer.currentItem.asset.duration;
    float myDuration = CMTimeGetSeconds(t2);

    float result = myDuration * thisPercent /100.0f;

    //NSLog(@"this result = %f",result); // debug

    CMTime seekTime = CMTimeMake(result, 1);

    [avPlayer seekToTime:seekTime];

}

答案 6 :(得分:1)

快速5

将此代码放在所需的某些函数中:

let duration = player.currentItem?.duration.seconds ?? 0
let playDuration = formatTime(seconds: duration) //Duration RESULT

创建一个名为:formatTime(seconds:Double)

的函数。
func formatTime(seconds: Double) -> String {
    let result = timeDivider(seconds: seconds)
    let hoursString = "\(result.hours)"
    var minutesString = "\(result.minutes)"
    var secondsString = "\(result.seconds)"

    if minutesString.count == 1 {
        minutesString = "0\(result.minutes)"
    }
    if secondsString.count == 1 {
        secondsString = "0\(result.seconds)"
    }

    var time = "\(hoursString):"
    if result.hours >= 1 {
        time.append("\(minutesString):\(secondsString)")
    }
    else {
        time = "\(minutesString):\(secondsString)"
    }
    return time
}

然后是另一个将秒转换为小时,分钟和秒的功能。由于layerLayer.player?.currentItem?.duration.seconds所具有的秒数将具有较长的Double,因此需要将其变为人类可读。

func timeDivider(seconds: Double) -> (hours: Int, minutes: Int, seconds: Int) {
    guard !(seconds.isNaN || seconds.isInfinite) else {
        return (0,0,0)
    }
    let secs: Int = Int(seconds)
    let hours = secs / 3600
    let minutes = (secs % 3600) / 60
    let seconds = (secs % 3600) % 60
    return (hours, minutes, seconds)
}

希望这是完整的答案。

答案 7 :(得分:0)

虽然这里的答案是正确的,但我认为补充一点很有价值,您可以要求 AVAsset 加载持续时间(或任何其他属性)并在加载后获得回调,以便您可以访问该值。这是对许多评论的回应,即 player.currentItem.asset.duration 的值在加载资产之前返回 0.00。

它像这样使用 AVAsynchronousKeyValueLoading

let asset = AVURLAsset(url: url)
asset.loadValuesAsynchronously(forKeys: ["duration"]) {
            
    var error: NSError? = nil
    let item: PlaylistItem
            
    // If the duration was loaded, construct a "normal" item,
    // otherwise construct an error item.
    switch asset.statusOfValue(forKey: "duration", error: &error) {
    case .loaded:
        item = PlaylistItem(url: url, title: title, artist: artist, duration: asset.duration)        
    case .failed where error != nil:
        item = PlaylistItem(title: title, artist: artist, error: error!) 
    default:
        let error = NSError(domain: NSCocoaErrorDomain, code: NSFileReadCorruptFileError)
        item = PlaylistItem(title: title, artist: artist, error: error)
    }           
}

此代码段来自 Apple 的 Playing Custom Audio with Your Own player 示例代码。