[ad_1]
I’ve about 200 native audio recordsdata displayed in a desk that I want to play so as. As every audio file performs, it can auto-scroll to the row.
Initially, I used to be attempting to make use of AVQueuePlayer, however issues bought actually sophisticated when attempting to derive the full time participant, implement searching for/scrubbing, integrating MPNowPlayingInfoCenter, and different performance. Additionally the time is uneven within the participant because it strikes from one audio file to the following. I am doing one thing like this:
@Printed public non-public(set) var gadgets = [AVPlayerItem]()
@Printed public non-public(set) var queuedItems = [AVPlayerItem]()
@Printed public non-public(set) var previousItems = [AVPlayerItem]()
@Printed public non-public(set) var currentItem: AVPlayerItem?
@Printed public non-public(set) var time: TimeInterval = 0
@Printed public non-public(set) var length: TimeInterval = 0
@Printed public non-public(set) var totalTime: TimeInterval = 0
@Printed public non-public(set) var totalDuration: TimeInterval = 0
@Printed public non-public(set) var remainingTime: TimeInterval = 0
@Printed public non-public(set) var progress = 0.0
non-public var participant: AVQueuePlayer?
non-public var previousDuration: TimeInterval = 0
non-public var cancellable = Set<AnyCancellable>()
non-public var timeObserverToken: Any?
// begin
gadgets = urls
.map(AVAsset.init)
.map(AVPlayerItem.init)
participant = AVQueuePlayer(gadgets: gadgets)
participant?.writer(for: .currentItem, choices: [.new, .old, .initial])
.scan(currentItem) { [weak self] in self?.replace(previousItem: $0, currentItem: $1); return $1 }
.assign(to: &$currentItem)
$gadgets
.map { $0.cut back(into: 0.0) { $0 += $1.asset.length.seconds } }
.assign(to: &$totalDuration)
timeObserverToken = participant?.addPeriodicTimeObserver(
forInterval: CMTime(seconds: 0.5, preferredTimescale: CMTimeScale(NSEC_PER_SEC)),
queue: .foremost,
) { [weak self] _ in
self?.updateProgress()
}
// helpers
func replace(previousItem: AVPlayerItem?, currentItem: AVPlayerItem?) {
queuedItems = Array(participant?.gadgets().drop { $0 == currentItem } ?? [])
participant?.gadgets().isEmpty == false ? previousItem.map { previousItems.append($0) } : nil // Skip if resetting
previousDuration = previousItems.cut back(into: 0.0) { $0 += $1.asset.length.seconds }
guard let currentItem = currentItem else {
time = 0
length = 0
return
}
length = currentItem.asset.length.seconds
updateProgress()
updateNowPlaying()
}
func updateProgress() {
guard let currentItem = currentItem else { return }
time = min(currentItem.currentTime().seconds, currentItem.asset.length.seconds)
totalTime = min(previousDuration + time, totalDuration)
remainingTime = max(totalDuration - totalTime, 0)
progress = totalDuration > 0 ? 1 - min(remainingTime / totalDuration, 1) : 0
}
func updateNowPlaying() {
guard let currentItem = currentItem else { return }
var data = MPNowPlayingInfoCenter.default().nowPlayingInfo ?? [String: Any]()
data[MPMediaItemPropertyTitle] = currentItem.url?.lastPathComponent ?? ""
data[MPMediaItemPropertyAlbumTitle] = "My playlist"
data[MPMediaItemPropertyPlaybackDuration] = totalDuration
data[MPNowPlayingInfoPropertyElapsedPlaybackTime] = totalTime
data[MPNowPlayingInfoPropertyPlaybackRate] = participant?.price ?? 0
data[MPNowPlayingInfoPropertyPlaybackQueueIndex] = gadgets.firstIndex(of: currentItem) ?? 0
data[MPNowPlayingInfoPropertyPlaybackQueueCount] = gadgets.depend
data[MPMediaItemPropertyArtwork] = UIImage(named: "cover-image")
.map { picture in MPMediaItemArtwork(boundsSize: CGSize(width: 1080, peak: 1080)) { _ in picture } }
MPNowPlayingInfoCenter.default().nowPlayingInfo = data
}
I then stumbled upon AVComposition and looks as if it might be a cleaner method to merge all 200 audio recordsdata into one giant one, and add time segments to it to deal with the auto-scrolling of the listing and updating MPNowPlayingInfoCenter.
How can I exploit AVComposition to merge all of the recordsdata and add time marks, but in addition How might I inform which audio is enjoying? Would this be the correct method or ought to I’m going again to AVQueuePlayer and hold refactoring what I’ve above? Thanks for any assist or perception.
[ad_2]
