Как создать видео из кадров ARSKView (или SKView), включая micro audio (ios 11)


Я играю с ARKit, и я хотел бы создать видео из кадров ARSKView. Я попытался использовать ReplayKit, но поведение не то, что я ожидал : - Я не хочу записывать весь экран целиком. - Я не хочу, чтобы пользователю было предложено, что мы записываем экран.

Кроме того, как я могу объединить микро-вход и видео ? Как я догадываюсь, аудио не передается в ARSKView? Вот код (из примера Apple):

import UIKit
import SpriteKit
import ARKit

class ViewController: UIViewController, ARSKViewDelegate {

    @IBOutlet var sceneView: ARSKView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Set the view's delegate
        sceneView.delegate = self

        // Show statistics such as fps and node count
        sceneView.showsFPS = true
        sceneView.showsNodeCount = true

        // Load the SKScene from 'Scene.sks'
        if let scene = SKScene(fileNamed: "Scene") {
            sceneView.presentScene(scene)
        }
    }

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

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

        // 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()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Release any cached data, images, etc that aren't in use.
    }

    // MARK: - ARSKViewDelegate

    func view(_ view: ARSKView, nodeFor anchor: ARAnchor) -> SKNode? {
        // Create and configure a node for the anchor added to the view's session.
        let labelNode = SKLabelNode(text: "
1 5

1 ответ:

Если вам нужно записать только кадры (как с AVCaptureSession, а не" реальную " 3D-сцену с SCNNodes), просто получите их как ARFrame.capturedImage в updateAtTime делегат функции SCNSceneRenderer:

func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
    createMovieWriterOnce(frame: session.currentFrame)
    appendFrameWithMetadaToMovie(frame: session.currentFrame)
}   

Я не нашел способа получить размер кадра из ARSession, поэтому MovieWriter ждет, пока первый кадр установит размер:

func createMovieWriterOnce(frame: ARFrame?) {
    if(frame == nil) { return }
    DispatchQueue.once(token: "SimplestMovieWriter.constructor") {
        movieWriter = SimplestMovieWriter(frameWidth: CVPixelBufferGetWidth(frame!.capturedImage), frameHeight: CVPixelBufferGetHeight(frame!.capturedImage))
    }
} 

И каждый следующий CVPixelBuffer подается в MovieWriter:

func appendFrameWithMetadaToMovie(frame: ARFrame?) {
    if(!isVideoRecording || frame == nil) { return }
    let interestingPoints = frame?.rawFeaturePoints?.points
    movieWriter.appendBuffer(buffer: (frame?.capturedImage)!, withMetadata: interestingPoints)
}

MovieWriter является ли пользовательский класс с AVAssetWriter, AVAssetWriterInput и AVAssetWriterInputPixelBufferAdaptor.

Вы можете сохранить видео без звука, а затем использовать AVAssetExportSession, чтобы добавить все, что вы хотите (аудио, субтитры, метаданные):

let composition = AVMutableComposition()
...
let trackVideo = composition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid)
let videoFileAsset = AVURLAsset(url: currentURL!, options: nil)
let videoFileAssetTrack = videoFileAsset.tracks(withMediaType: AVMediaTypeVideo)[0]

// add audio track here