SwiftAudio
SwiftAudio copied to clipboard
[Question] Get total duration
Is it possible to get total duration of a remote audio file?
By using the event updateDuration
event the duration is continually updated (I think until everything has been downloaded/buffered?). This makes the knob on a seek bar/scrubber jump around until duration has been determined and are perceived quite buggy and hard to use by our users.
PS. Thanks for an awesome lib! :)
Additional info: If I start playback of a file and take a look at the lock screen, the full duration is available even though I'm still getting updateDuration
from SwiftAudio
.
Tested on a device using iOS 13.
I see that that the duration is available using player.duration
at some point, but when is it safe to assume it is available? What's the purpose of event updateDuration
that does not contain the total duration?
The updateDuration
event is called whenever the AVPlayerItem changes its duration
. You can use this to know when the duration changes. If if seems to change abnormally I can take a look into it.
The class that is the source of the event is the AVPlayerItemObserver
.
To my knowledge you can assume that the player.duration
is available when the state changes to ready
In my case, updateDuration
seems to update continuously. Looking a AVPlayerItemObserver
it seems clear why.
Code:
player.event.stateChange.addListener(self) { [weak self] state in
if ["ready", "playing"].contains(state.rawValue) {
print("⌛ stateChange (to ready, playing) - player.duration: \(self?.player.duration)")
}
}
player.event.updateDuration.addListener(self) { [weak self] duration in
print("⌛ updateDuration: \(duration)")
}
Output:
⌛ stateChange (to ready, playing) - player.duration: Optional(1246.4848979591836)
⌛ updateDuration: 0.4963265306122449
⌛ updateDuration: 30.48307925
⌛ updateDuration: 67.341854761
⌛ updateDuration: 122.643079251
⌛ updateDuration: 158.822671088
⌛ updateDuration: 196.360630272
⌛ updateDuration: 233.245528232
⌛ updateDuration: 270.104303743
⌛ updateDuration: 306.963079254
⌛ updateDuration: 343.821854765
⌛ updateDuration: 380.680630276
⌛ updateDuration: 417.565528236
⌛ updateDuration: 454.424303747
⌛ updateDuration: 509.725528237
⌛ updateDuration: 546.584303748
⌛ updateDuration: 583.443079259
⌛ updateDuration: 637.359813954
⌛ updateDuration: 674.923895587
⌛ updateDuration: 711.782671098
⌛ updateDuration: 748.641446609
⌛ updateDuration: 803.942671099
⌛ updateDuration: 840.122262936
⌛ updateDuration: 877.66022212
⌛ updateDuration: 929.565528244
⌛ updateDuration: 965.745120081
⌛ updateDuration: 1002.603895592
⌛ updateDuration: 1039.462671103
⌛ updateDuration: 1076.321446614
⌛ updateDuration: 1111.821854778
⌛ updateDuration: 1168.481446615
⌛ updateDuration: 1205.340222126
⌛ updateDuration: 1246.4848979591836
I tried using player.duration
when state changes to ready
, but if you pass playWhenReady: true
, state goes directly from loading
to playing
, never entering ready
state. A workaround is to access player.duration
when state changes to ready
or playing
, but that is not optimal.
The updateDuration
seems to work as intended, it is only intended to send events whenever the item updates its duration value. Does your scrub behave better with your PR #87 and using the player's ready state?
As for the incorrect state, that is interesting and definitely seems like a bug 🐛You can move it to a separate ticket and I will do some testing too 👍
With the PR, I can access player.duration
when ready
and scrubbing works perfectly :)
I don't think I completely understand the updateDuration
event though, if it's working as intended. Why does it emit intermediate duration values up until the final full duration when the full duration it is already on ready
?