Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Portrait videos no longer retain aspect ratio in iOS 14

Tags:

swift

video

ios14

Using version Texture 3.0.0 with XCode 12 and iOS 14, a problem that appears only on iOS 14 devices, is that portrait videos load with the wrong resolution (it may seem that they swap their width with their height).

Auto play works fine, but manual play does not. Portrait videos are broken, but landscape videos are not. The issue is that the gravity applied seems to stretch the video using the wrong width/height for portrait videos.

Sample app below (using a public portrait video I uploaded):

//
//  ViewController.swift
//  test video
//
//  Created by Ericos Georgiades on 22/09/2020.
//

import UIKit
import AVFoundation
import AsyncDisplayKit

class ViewController: UIViewController {

    
    @IBOutlet weak var videoView: UIView!
    private let videoNode = ASVideoNode();
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        videoNode.gravity = AVLayerVideoGravity.resizeAspectFill.rawValue;
        videoNode.muted = true;
        videoNode.shouldAutorepeat = true;
        videoNode.shouldAutoplay = false; // works if true
        videoView.addSubnode(videoNode);
        videoNode.frame = videoView.frame;
        
        let asset = AVAsset(url: URL(string: "https://storage.googleapis.com/pao-uat-6b24c.appspot.com/users/0QhK2lnaQ49BftJTRQ46/spots/7q0Q2TjiIyHyrNTBbJOO/media/WaMnS8Np5vkTcIV0rGyJ/WaMnS8Np5vkTcIV0rGyJ?alt=media&token=75542345-06cc-4e37-a422-1ff2a1cf47c2")!)
        videoNode.asset = asset

        DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
            self.videoNode.play();
        }
    }
}

I have yet to figure out if this is a bug with the library or if this is possible to resolve in Swift without a library fix (or if its needed at all).

Also posted as a bug on https://github.com/TextureGroup/Texture/issues/1918

like image 866
ericosg Avatar asked Oct 05 '20 12:10

ericosg


1 Answers

Try to call didExitPreloadState() before play():

...
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
      self.videoNode.didExitPreloadState()
      self.videoNode.play();
}
...

In the sample they set the asset immediately before play(). The setter of the asset calls didExitPreloadState() internally (see here).

like image 200
atarasenko Avatar answered Oct 06 '22 14:10

atarasenko