Skip to content

Instantly share code, notes, and snippets.

@damodarnamala
Forked from shaps80/AVPlayer+Scrubbing.swift
Created September 16, 2022 04:24
Show Gist options
  • Save damodarnamala/ec47f222d058664ba885382a5df317e1 to your computer and use it in GitHub Desktop.
Save damodarnamala/ec47f222d058664ba885382a5df317e1 to your computer and use it in GitHub Desktop.
Enables smooth frame-by-frame scrubbing (in both directions) – similar to Apple's applications.
public enum Direction {
case forward
case backward
}
internal var player: AVPlayer?
private var isSeekInProgress = false
private var chaseTime = kCMTimeZero
private var preferredFrameRate: Float = 23.98
public func seek(to time: CMTime) {
seekSmoothlyToTime(newChaseTime: time)
}
public func stepByFrame(in direction: Direction) {
let frameRate = preferredFrameRate
?? player?.currentItem?.tracks
.first(where: { $0.assetTrack.mediaType == .video })?
.currentVideoFrameRate
?? -1
let time = player?.currentItem?.currentTime() ?? kCMTimeZero
let seconds = Double(1) / Double(frameRate)
let timescale = Double(seconds) / Double(time.timescale) < 1 ? 600 : time.timescale
let oneFrame = CMTime(seconds: seconds, preferredTimescale: timescale)
let next = direction == .forward
? CMTimeAdd(time, oneFrame)
: CMTimeSubtract(time, oneFrame)
seekSmoothlyToTime(newChaseTime: next)
}
private func seekSmoothlyToTime(newChaseTime: CMTime) {
if CMTimeCompare(newChaseTime, chaseTime) != 0 {
chaseTime = newChaseTime
if !isSeekInProgress {
trySeekToChaseTime()
}
}
}
private func trySeekToChaseTime() {
guard player?.status == .readyToPlay else { return }
actuallySeekToTime()
}
private func actuallySeekToTime() {
isSeekInProgress = true
let seekTimeInProgress = chaseTime
player?.seek(to: seekTimeInProgress, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero) { [weak self] _ in
guard let `self` = self else { return }
if CMTimeCompare(seekTimeInProgress, self.chaseTime) == 0 {
self.isSeekInProgress = false
} else {
self.trySeekToChaseTime()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment