I am trying to chroma key a video in ARKit, and I have done very similar to what @Felix has done here: GPUImageView inside SKScene as SKNode material - Playing transparent video on ARKit
But, when the video is supposed to show up (in this case, when an AR reference image is detected) I get a [SceneKit] Error: Cannot get pixel buffer (CVPixelBufferRef)
error and the video no longer plays. It did play before I implemented the chromaKeyMaterial
. Here is my code, starting from just after the AR refernce image is detected:
DispatchQueue.main.async {
let filePath = Bundle.main.path(forResource: "wigz", ofType: "mp4")
let videoURL = NSURL(fileURLWithPath: filePath!)
let player = AVPlayer(url: videoURL as URL)
let spriteKitScene = SKScene(size: CGSize(width: 640, height: 480))
let videoSpriteKitNode = SKVideoNode(avPlayer: player)
let videoNode = SCNNode()
videoNode.geometry = SCNPlane(width: imageAnchor.referenceImage.physicalSize.width,
height: imageAnchor.referenceImage.physicalSize.height)
videoNode.eulerAngles = SCNVector3(-Float.pi/2, 0, 0)
// Use spritekit with videonode inside
spriteKitScene.scaleMode = .aspectFit
videoSpriteKitNode.position = CGPoint(x: spriteKitScene.size.width / 2,
y: spriteKitScene.size.height / 2)
videoSpriteKitNode.size = spriteKitScene.size
videoSpriteKitNode.yScale = -1.0
videoSpriteKitNode.play()
// Loop video
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: player.currentItem, queue: .main) { _ in
player.seek(to: kCMTimeZero)
player.play()
}
spriteKitScene.addChild(videoSpriteKitNode)
videoNode.geometry?.firstMaterial?.diffuse.contents = spriteKitScene
videoNode.geometry?.firstMaterial?.isDoubleSided = true
let chromaKeyMaterial = ChromaKeyMaterial()
chromaKeyMaterial.diffuse.contents = player
videoNode.geometry!.materials = [chromaKeyMaterial]
node.addChildNode(videoNode)
self.imageDetectView.scene.rootNode.addChildNode(node)
}
In the ChromaKeyMaterial.swift file, i have changed these lines to:
float maskY = 0.0 * c_colorToReplace.r + 1.0 * c_colorToReplace.g + 0.0 * c_colorToReplace.b;
float maskCr = 0.7132 * (c_colorToReplace.r - maskY);
float maskCb = 0.5647 * (c_colorToReplace.b - maskY);
float Y = 0.0 * textureColor.r + 1.0 * textureColor.g + 0.0 * textureColor.b;
float Cr = 0.7132 * (textureColor.r - Y);
float Cb = 0.5647 * (textureColor.b - Y);
In an effort to chroma key out a pure green, but I am not sure if that is the correct approach.
Any help would be greatly appreciated!
SKScene
and aSKVideoNode
is not necessary. You can directly set theAVPlayer
as the contents of aSCNMaterialProperty
instance. – Inconvenient