web-dev-qa-db-ja.com

iOS 7でiOS 7 AVPlayer AVPlayerItemの期間が正しくない

アプリに次のコードがあります。

NSURL *url = [NSURL fileURLWithPath: [self.DocDir stringByAppendingPathComponent: self.FileName] isDirectory: NO];
self.avPlayer = [AVPlayer playerWithURL: url];

Float64 duration = CMTimeGetSeconds(self.avPlayer.currentItem.duration);

これはiOS 6では問題なく動作しましたが、何らかの理由でiOS 7ではNaNを返します。 self.avPlayer.currentItem.durationを検査するとき、CMTimeオブジェクトには0があり、フラグは17です。

興味深いことに、プレーヤーは正常に動作しますが、期間が間違っています。

他の誰かが同じ問題を経験しましたか?以下をインポートしています:

#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
#import <MediaPlayer/MediaPlayer.h>
#import <CoreMedia/CoreMedia.h>
#import <AVFoundation/AVAsset.h>
28
Matt Wolfe

オブジェクトを初期化するさまざまな方法を試した後、実用的なソリューションにたどり着きました。

AVURLAsset *asset = [AVURLAsset assetWithURL: url];
Float64 duration = CMTimeGetSeconds(asset.duration);
AVPlayerItem *item = [AVPlayerItem playerItemWithAsset: asset]; 
self.avPlayer = [[AVPlayer alloc] initWithPlayerItem: item];

期間の値がAVPlayerItemからすぐに利用できるとは限らないようですが、AVAssetですぐに正常に動作するようです。

50
Matt Wolfe

IOS 7では、すでに作成されているAVPlayerItemの場合、下にあるアセットから期間を取得することもできます。

CMTimeGetSeconds([[[[self player] currentItem] asset] duration]);

NaVを与えるAVPlayerItemから直接取得する代わりに:

CMTimeGetSeconds([[[self player] currentItem] duration]);
27
Derek Li

マニュアル で説明されている、これを行うための推奨方法は、プレーヤーのアイテムのステータスを監視することです。

[self.avPlayer.currentItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionInitial context:nil];

次に、observeValueForKeyPath:ofObject:change:context

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    // TODO: use either keyPath or context to differentiate between value changes
    if (self.avPlayer.currentItem.status == AVPlayerStatusReadyToPlay) {
        Float64 duration = CMTimeGetSeconds(self.avPlayer.currentItem.duration);
        // ...
    }
}

また、プレーヤーアイテムを変更するときは、必ずオブザーバーを削除してください。

if (self.avPlayer.currentItem) {
    [self.avPlayer.currentItem removeObserver:self forKeyPath:@"status"];
}

ところで、durationプロパティを直接監視することもできます。ただし、結果が期待どおりに信頼できないのは私の個人的な経験です;-)

5
Ja͢ck

Swiftバージョン

AVAssetプロパティであるAVPlayerItemを使用して期間を取得できます。

func getVideoDuration(from player: AVPlayer) -> Double? {
    guard let duration = player.currentItem?.asset.duration else { return nil }
    let durationSeconds = CMTimeGetSeconds(duration)
    return durationSeconds
}

または、最初からAVAssetを作成します。

func getVideoDuration(for videoUrl: URL) -> Double {
    let asset = AVAsset(url: videoUrl)
    let duration = asset.duration
    let durationSeconds = CMTimeGetSeconds(duration)
    return durationSeconds
}
0
Trzy Gracje