我一直跟着Yuma的this excellent tutorial一起工作,并且有一些工作要做。下面是我在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本身发生的任何内部错误?
答案 0 :(得分:3)
可能是因为您的视频尺寸很大。您需要先等待 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)
}
}
答案 1 :(得分:0)
我已经使用下面的代码正常播放了各种文件大小和比例的视频。
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
}
})