1

ビデオ ファイル内の CMTime と fps の機能を理解しようとしています。forループを使用して、AVPlayerでビデオのすべてのフレームを表示しようとしています。このタスクは、AVPlayer の play メソッドを使用して簡単に実行できることを知っています。しかし、フレームがどのように正確に表示されるかを知りたいです。for ループを作成し、AVPlayer の seekToTime メソッドを常に更新することで、各フレームを 1 つずつ表示しようとしました。解決策を開発することはできますが、すべてのフレームが表示されず、ビデオがぎこちなく見えます。

これは私のコードです:

for(float t=0; t < asset.duration.value; t++)
{
    CMTime tt = CMTimeMake(t, asset.duration.timescale);
    [self.player seekToTime:tt];
    NSLog(@"%lld, %d",tt.value, tt.timescale);
}

ここで、player は AVPlayer のインスタンス、asset は提示しようとしているフレームのビデオ アセットです。CMTimeMakeSeconds(t, asset.duration.timescale) も使用してみましたが、うまくいきませんでした。

あなたの提案をしてください。ありがとうございました。

4

1 に答える 1

0

一般に、1 秒あたりのフレーム数は、ビデオ ファイルでは一定ではありません。フレームは発生時に発生します。AVAssetReaderそれがいつなのかを知りたい場合は、 クラスとAVAssetReaderTrackOutputクラスを使用してフレームのプレゼンテーション タイムスタンプを調べることができます。

let reader = try! AVAssetReader(asset: asset)

let videoTrack = asset.tracksWithMediaType(AVMediaTypeVideo)[0]
let trackReaderOutput = AVAssetReaderTrackOutput(track: videoTrack, outputSettings:nil)

reader.addOutput(trackReaderOutput)
reader.startReading()

while let sampleBuffer = trackReaderOutput.copyNextSampleBuffer() {
    // pts shows when this frame is presented
    // relative to the start of the video file
    let pts = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
}

あなたのコードでは、ビデオのタイムラインを誤ってサンプリングしています。これを 30 fps でサンプリングする方法を次に示します (前述のように、これはおそらく実際のフレーム境界に対応していません)。

for (CMTime t = kCMTimeZero; CMTimeCompare(t, asset.duration) < 0;  t = CMTimeAdd(t, CMTimeMake(1, 30))) {
    [player seekToTime:t];
}
于 2016-09-24T23:42:01.363 に答える