Отображение видеокадров без использования метода воспроизведения в iOS

Я пытаюсь понять функционирование CMTime и fps в видеофайле. Я пытаюсь представить каждый кадр видео в AVPlayer, используя цикл for. Я знаю, что эту задачу легко выполнить, используя метод воспроизведения AVPlayer. Но я хочу знать, как именно отображаются кадры. Я создал цикл for и пытаюсь представить каждый кадр один за другим, постоянно обновляя метод seekToTime в AVPlayer. Я могу разработать решение, но оно не показывает все кадры, а видео выглядит вяло.

Это мой код:

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, ресурс - это видео ресурс, кадры которого я пытаюсь представить. Я также пытался использовать CMTimeMakeSeconds(t, asset.duration.timescale), но не сработало.

Пожалуйста, дайте ваше предложение. Спасибо.

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 кадров в секунду (как упоминалось выше, это, вероятно, не будет соответствовать фактическим границам кадра):

for (CMTime t = kCMTimeZero; CMTimeCompare(t, asset.duration) < 0;  t = CMTimeAdd(t, CMTimeMake(1, 30))) {
    [player seekToTime:t];
}
Другие вопросы по тегам