I have an ARSCNView with virtual objects drawn. The virtual objects are drawn on the user's face. The session has the following configuration:
let configuration = ARFaceTrackingConfiguration()
configuration.worldAlignment = .gravityAndHeading
sceneView.session.run(configuration)
This ARSCNView is part of a video call. If we send back the pixel buffer like below,
public func session(_ session: ARSession, didUpdate frame: ARFrame) {
videoSource.sendBuffer(frame.capturedImage, timestamp: frame.timestamp)
}
The virtual objects are not shown to my caller.
One of the things I tried is, to not rely on ARSessionDelegate's callback but use DispatchSourceTimer to send events.
func startCaptureView() {
// Timer with 0.1 second interval
timer.schedule(deadline: .now(), repeating: .milliseconds(100))
timer.setEventHandler { [weak self] in
// Turn sceneView data into UIImage
guard let sceneImage: CGImage = self?.sceneView.snapshot().cgImage else {
return
}
self?.videoSourceQueue.async { [weak self] in
if let buffer: CVPixelBuffer = ImageProcessor.pixelBuffer(forImage: sceneImage) {
self?.videoSource.sendBuffer(buffer, timestamp: Double(mach_absolute_time()))
}
}
}
timer.resume()
}
The caller receives the data slowly with a choppy video experience and the images are not of the right size.
Any suggestions on how to send data about the virtual object along with the captured frame?
Reference: https://medium.com/agora-io/augmented-reality-video-conference-6845c001aec0
The reason the Virtual objects are not appearing is because ARKit provides only the raw image, so
frame.capturedImageis the image captured by the camera, without any of the SceneKit rendering. To pass the rendered video you will need to implement an offscreenSCNRendererand pass the pixel buffer to Agora's SDK.I would recommend you check out the Open Source framework AgoraARKit. I wrote the framework and it implements Agora.io Video SDK and ARVideoKit as dependancies. ARVideoKit is a popular library that implements an off-screen renderer and provides the rendered pixel buffer.
The library implements WorldTracking by default. If you want to extend the
ARBroadcasterclass to implement faceTracking you could use this code: