Отображение видеокадров без использования метода воспроизведения в 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];
}