I have a very simple audio player which plays mp3s from a url
func start() {
if let url = URL(string: cloudinaryUrl) {
self.avPlayerItem = AVPlayerItem(url: url)
self.avPlayer = AVPlayer(playerItem: avPlayerItem)
self.avPlayer?.rate = Float(rate.rate)
self.avPlayer?.play()
}
}
And a slider that represents the track:
///View Model
func setTime(_ newValue: Double) {
guard let avPlayer = avPlayer, let avPlayerItem = avPlayerItem else { return }
let clampedValue = max(0, min(1, newValue))
let time = CMTimeGetSeconds(avPlayerItem.duration) * clampedValue
let cmtime: CMTime = CMTimeMake(value: Int64(time * 1000 as Float64), timescale: 1000)
avPlayer.seek(to: cmtime, toleranceBefore: .zero, toleranceAfter: .zero)
}
// SwiftUI View
@State var slider: Double = 0
Slider(value: $slider, in: 0...1, onEditingChanged: { moving in
viewModel.setTime(slider)
})
This works well, and I can move the slider to where I want the audio to start and it does consistently.
However, I have a list of buttons with TimeIntervals e.g. 27.320. When I click the button I want to jump to the point in time with my audio player. However, it seems to not consistently go to the timestamp, and I’m unsure why. Weirdly, it’ll play correctly the first time, then subsequent clicks play a second or two back.
// view model
func setTranscriptTime(_ newValue: Double) {
guard let avPlayer = avPlayer else {
setError(error: .noPlayer)
return
}
let cmtime: CMTime = CMTimeMake(
value: Int64(newValue * 1000 as Float64),
timescale: 1000
)
print(cmtime)
avPlayer.seek(
to: cmtime,
toleranceBefore: .zero,
toleranceAfter: .zero
)
}
// view
Button(action: {
viewModel.setTranscriptTime(dialogue[index].startTime)
}) {
Text(line.text)
}
This prints
CMTime(value: 27320, timescale: 1000, flags: __C.CMTimeFlags(rawValue: 1), epoch: 0)
Which is what I expected and with the tolerance as zero, I’m unsure why this would be off at all. Would appreciate some advice! Thanks