Using an AVQueuePlayer to display a number of videos in sequence, there seems to be issues with transitioning between items with different aspect ratios.
This is the view controller code:
The view and view protocol code:
This is a transition between a portrait and landscape video, slowed down to 12% speed:
giphy.com/gifs/P2pRbh6zgSlTuLnGXb
Any suggestions on what I can do to avoid this? I've looked into switching video layers to transition between items with some success, but I'd rather not fight the framework if I can avoid it
This is the view controller code:
Code Block class ExampleLayerViewController<T: PlayerView>: UIViewController { var playerView: T { view as! T } var viewModel = LayerViewModel() let buttonStack: UIStackView = { /* make stack view */ }() let playButton: UIButton = { /* make button */ }() let pauseButton: UIButton = { /* make button */ }() let skip: UIButton = { /* make button */ }() let previous: UIButton = { /* make button */ }() override func viewDidLoad() { super.viewDidLoad() addConstraints() enqueue() } override func loadView() { view = T() } func addConstraints() { /* add buttons to stack and put stack at bottom */ } func enqueue() { playerView.enqueue(with: viewModel.assets) } @objc func playButtonPressed() { playerView.play() } @objc func pauseButtonPressed() { playerView.pause() } @objc func previousButtonPressed() { playerView.previous() } @objc func nextButtonPressed() { playerView.skip() } }
The view and view protocol code:
Code Block protocol PlayerView: UIView { func play() func pause() func skip() func previous() func enqueue(with urls: [URL]) var state: PlayerState { get } } enum PlayerState { case playWhenReady, pause, stop, interrupted } class QueuePlayerView: UIView, PlayerView { var playerLayer: AVPlayerLayer? { return layer as? AVPlayerLayer } var queuePlayer: AVQueuePlayer! var state: PlayerState = .stop init() { super.init(frame: .zero) setupQueuePlayer() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override static var layerClass: AnyClass { return AVPlayerLayer.self } override func layoutSubviews() { playerLayer?.frame = bounds } private func setupQueuePlayer() { queuePlayer = AVQueuePlayer() playerLayer?.player = queuePlayer playerLayer?.videoGravity = .resizeAspectFill queuePlayer?.actionAtItemEnd = .advance } func play() { state = .playWhenReady queuePlayer.play() } func pause() { state = .pause queuePlayer.pause() } func skip() { queuePlayer.advanceToNextItem() } func previous() { /* yeah I know */ queuePlayer.seek(to: CMTime.zero) } func enqueue(with urls: [URL]) { urls.forEach { queuePlayer.insert(AVPlayerItem(url: $0), after: nil) } } }
This is a transition between a portrait and landscape video, slowed down to 12% speed:
giphy.com/gifs/P2pRbh6zgSlTuLnGXb
Any suggestions on what I can do to avoid this? I've looked into switching video layers to transition between items with some success, but I'd rather not fight the framework if I can avoid it