AVFoundation проблема воспроизведения видео - PullRequest
2 голосов
/ 22 марта 2019

Я последовал вместе с этим превосходным учебником от Юмы и у меня что-то работает.Ниже приведен код, который я использую в моем viewcontroller

import UIKit
import SceneKit
import ARKit
import AVFoundation
import SpriteKit

class ViewController: UIViewController, ARSCNViewDelegate {

    @IBOutlet var sceneView: ARSCNView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Set the view's delegate
        sceneView.delegate = self

        // Show statistics such as fps and timing information
        sceneView.showsStatistics = true

        // Create a new scene
        let scene = SCNScene(named: "art.scnassets/notebook.scn")!

        // Set the scene to the view
        sceneView.scene = scene
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        // Create a session configuration
        let configuration = ARImageTrackingConfiguration()

        guard let arImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: nil) else { return }
        configuration.trackingImages = arImages
        // Run the view's session
        sceneView.session.run(configuration)
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)

        // Pause the view's session
        sceneView.session.pause()
    }
    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
        guard anchor is ARImageAnchor else { return }

        // Amy Image recognition
        guard let amyContainer = sceneView.scene.rootNode.childNode(withName: "amy", recursively: false) else { return }
        amyContainer.removeFromParentNode()
        node.addChildNode(amyContainer)
        amyContainer.isHidden = false

        // Video
        let videoURL = Bundle.main.url(forResource: "video", withExtension: "mp4")!

        let videoPlayer = AVPlayer(url: videoURL)

        let videoScene = SKScene(size: CGSize(width: 900.0, height: 1400.0))

        let videoNode = SKVideoNode(avPlayer: videoPlayer)

        videoNode.position = CGPoint(x: videoScene.size.width / 2, y: videoScene.size.height / 2)

        videoNode.size = videoScene.size

        videoNode.yScale = -1

        videoNode.play()

        videoScene.addChild(videoNode)

        guard let video = amyContainer.childNode(withName: "video", recursively: true)
        else { return }
    video.geometry?.firstMaterial?.diffuse.contents = videoScene

 }
 }

Когда я использую видео, которое было предоставлено в качестве части учебного пособия, все работает отлично, но когда я пытаюсь включить видео, которое у меня естьСоздано, я получаю только белое поле над целевым изображением, но без видео.

Я утроил, проверил имя, я попытался экспортировать видео с точно такими же размерами, но все безуспешно.Я протестировал загрузку новой версии видео, которая работает под другим именем, и изменил имена, и это работает, поэтому я должен предположить, что я создаю .mp4, и это проблема.

Существуют ли определенные правила / настройки, которые требуются для mp4 для такого подхода, есть ли настройка в Premiere Pro или Handbrake, которую я могу использовать?Или как я могу отладить любые внутренние ошибки, которые происходят через сам Xcode?

Ответы [ 2 ]

3 голосов
/ 24 марта 2019

Возможно, размер вашего видео большой. Вам нужно подождать, прежде чем AVPlayer будет готов, прежде чем пытаться воспроизвести ваше видео

class ViewController: UIViewController, ARSCNViewDelegate {

    @IBOutlet var sceneView: ARSCNView!
    var observer: NSKeyValueObservation?
    var videoNode: SKVideoNode?

    override func viewDidLoad() {
        super.viewDidLoad()

        // Set the view's delegate
        sceneView.delegate = self

        // Show statistics such as fps and timing information
        sceneView.showsStatistics = true

        // Create a new scene
        let scene = SCNScene(named: "art.scnassets/notebook.scn")!

        // Set the scene to the view
        sceneView.scene = scene
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        // Create a session configuration
        let configuration = ARImageTrackingConfiguration()

        guard let arImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: nil) else { return }
        configuration.trackingImages = arImages
        // Run the view's session
        sceneView.session.run(configuration)
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)

        // Pause the view's session
        sceneView.session.pause()
    }
    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
        guard anchor is ARImageAnchor else { return }

        // Amy Image recognition
        guard let amyContainer = sceneView.scene.rootNode.childNode(withName: "amy", recursively: false) else { return }
        amyContainer.removeFromParentNode()
        node.addChildNode(amyContainer)
        amyContainer.isHidden = false

        let videoPlayer = self.createAVPlayer()

        let videoScene = SKScene(size: CGSize(width: 900.0, height: 1400.0))

        self.videoNode = SKVideoNode(avPlayer: videoPlayer)

        self.videoNode?.position = CGPoint(x: videoScene.size.width / 2, y: videoScene.size.height / 2)

        self.videoNode?.size = videoScene.size

        self.videoNode?.yScale = -1

        videoScene.addChild(self.videoNode!)

        guard let video = amyContainer.childNode(withName: "video", recursively: true)
            else { return }
        video.geometry?.firstMaterial?.diffuse.contents = videoScene

    }

    func createAVPlayer() -> AVPlayer {
        let videoURL = Bundle.main.url(forResource: "video", withExtension: "mp4")!
        let asset = AVAsset(url: videoURL)

        let assetKeys = [
            "playable",
            "hasProtectedContent"
        ]
        let playerItem = AVPlayerItem(asset: asset,
                                      automaticallyLoadedAssetKeys: assetKeys)

        self.observer = playerItem.observe(\.status, options:  [.new, .old], changeHandler: { (playerItem, change) in
            if playerItem.status == .readyToPlay {

                self.videoNode?.play() // Only play when Its ready
            }
        })

        return AVPlayer(playerItem: playerItem)
    }
}
0 голосов
/ 19 июня 2019

Я использовал приведенный ниже код без проблем для воспроизведения видео с различным размером и масштабом файла.

    let videoURL = URL(fileURLWithPath: Bundle.main.path(forResource: videoAssetName, ofType: videoAssetExtension)!)
    let player = AVPlayer(url: videoURL)
    player.actionAtItemEnd = .none
    videoPlayerNode = SKVideoNode(avPlayer: player)

    // setup player
    let skSceneSize = orientation == .horizontal ? CGSize(width: 1280, height: 720) : CGSize(width: 406, height: 720)
    let skScene = SKScene(size: skSceneSize)
    skScene.addChild(videoPlayerNode)

    videoPlayerNode.position = CGPoint(x: skScene.size.width/2, y: skScene.size.height/2)
    videoPlayerNode.size = skScene.size

    let scnPlaneSize : [String : CGFloat] = orientation == .horizontal ? ["width": 0.9, "height": 0.5063] : ["width": 0.5063, "height": 0.9]
    let videoPlane = SCNPlane(width: scnPlaneSize["width"]!, height: scnPlaneSize["height"]!)
    videoPlane.firstMaterial?.diffuse.contents = skScene
    videoPlane.firstMaterial?.isDoubleSided = true

    let videoPlaneNode = SCNNode(geometry: videoPlane)
    videoPlaneNode.eulerAngles = SCNVector3(180.degreesToRadians, 180.degreesToRadians, 0) // rotate video node to counter flip caused by contraint on adNode
    amyContainer.addChildNode(videoPlaneNode)

    // setup node to auto remove itself upon completion
    NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: player.currentItem, queue: nil, using: { (_) in
        DispatchQueue.main.async {
            // do something on video end
        }
    })
...