Я играю с ARKit и создал приложение, которое накладывает видеоконтент на распознанные изображения. Код выглядит следующим образом:
import UIKit
import SceneKit
import ARKit
import SpriteKit
class ViewController: UIViewController, ARSCNViewDelegate {
@IBOutlet var sceneView: ARSCNView!
override func viewDidLoad() {
super.viewDidLoad()
sceneView.delegate = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let configuration = ARImageTrackingConfiguration()
if let imageToTrack = ARReferenceImage.referenceImages(inGroupNamed: "ALLimages", bundle: Bundle.main) {
configuration.trackingImages = imageToTrack
configuration.maximumNumberOfTrackedImages = 3
print("Images successfully added")
}
sceneView.session.run(configuration)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
sceneView.session.pause()
}
// MARK: - ARSCNViewDelegate
func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
let node = SCNNode()
var videoNode = SKVideoNode()
var videoScene = SKScene()
if let imageAnchor = anchor as? ARImageAnchor {
videoNode = SKVideoNode(fileNamed: "video1.mp4")
videoNode.play()
videoScene = SKScene(size: CGSize(width: 640, height: 360))
videoNode.position = CGPoint(x: videoScene.size.width / 2, y: videoScene.size.height / 2)
videoNode.yScale = -1.0
videoScene.addChild(videoNode)
let plane = SCNPlane(width: imageAnchor.referenceImage.physicalSize.width, height: imageAnchor.referenceImage.physicalSize.height)
plane.firstMaterial?.diffuse.contents = videoScene
let planeNode = SCNNode(geometry: plane)
planeNode.eulerAngles.x = -.pi/2
node.addChildNode(planeNode)
}
return node
}
}
Это прекрасно работает ... однажды! Но проблема в том, что после завершения воспроизведения видео из-за ограниченных элементов управления, доступных через SKVideoNode, я не могу понять, как автоматически перезапустить видео. В идеале они должны воспроизводиться в виде петли.
Я провел некоторое исследование, и мне кажется, что лучший способ - это инициализировать мой видеоузел с помощью объекта AVPlayer.
Итак, я попытался сделать это, но не могу заставить его работать.
Я добавил var player = AVPlayer () в свой класс, а затем попытался инициализировать свой videoNode следующим образом:
var videoNode: SKVideoNode? = {
guard let urlString = Bundle.main.path(forResource: "video1", ofType: "mov") else {
return nil
}
let url = URL(fileURLWithPath: urlString)
let item = AVPlayerItem(url: url)
let player = AVPlayer(playerItem: item)
return SKVideoNode(avPlayer: player)
}()
Затем я попытался использовать player.play (), но видео не воспроизводится. Вместо этого мой самолет просто выглядит как пустой прямоугольник над моими изображениями.
Как только я успешно инициализирую это, я думаю, что смогу добавить наблюдателя, чтобы проверить, когда видео закончил проигрыватель, и перезапустить его, но я изо всех сил пытаюсь добраться до этой точки.