ARKit開發從入門到精通(2)--- 將AR內容錄製保存爲視頻、Gif

這部分教程我們使用一個第三方框架ARVideoKit來實現將AR效果錄製成視頻或gif動圖。這個框架是由蘋果的ARKit、AVFoundation、Metal和CoreMedia構建的,它去掉了用設備的camera流呈現ARSCNView或ARSKView內容的複雜部分。

關於ARVideoKit

  • 從ARSCNView、ARSKView和SCNView捕捉照片
  • 從ARSCNView、ARSKView和SCNView捕捉Live Photos和gif
  • 錄製來自ARSCNView、ARSKView和SCNView的視頻
  • 暫停/播放視頻
  • 允許設備的音樂在後臺播放,同時錄製視頻

 

實現效果預覽:

ARKit+SpriteKit-GIF

 

Step 1:新建項目

首先下載ARVideoKit(本次案例演示使用的是1.11版本)的Framework.zip文件。

 

在Xcode創建ARKit + SpriteKit項目

Create Xcode Project

接下來添加FrameWork

1.在項目文件夾中創建一個名爲Frameworks的文件夾。

Recording ARKit Videos & Animated GIFs Using ARVideoKit 1

2.將下載的ARVideoKit.framework複製到Frameworks文件夾中

copy_framework

3.將ARVideoKit.framework拖放到項目target’s embedded binaries中。確保選中“Copy items if needed”。

add-arkitvideo-framework

 

配置Framework

1.通過添加以下語句,在AppDelegate.swift中導入ARVideoKit:

import ARVideoKit

2.在AppDelegate.swift類中添加以下方法,允許以不同的方向錄製視頻和gif文件。

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    return ViewAR.orientation
}

完整代碼如下:

import UIKit
import ARVideoKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        return true
    }

    func applicationWillResignActive(_ application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
    }

    func applicationDidEnterBackground(_ application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }

    func applicationWillEnterForeground(_ application: UIApplication) {
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

    func applicationWillTerminate(_ application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }

    
    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        return ViewAR.orientation
    }

}

Step 2:添加User Interface

創建3個簡單的按鈕:Record/Stop、Pause/Resume和Capture gif。在ViewController類中聲明以下屬性:

var recorderButton:UIButton = {
    let btn = UIButton(type: .system)
    btn.setTitle("Record", for: .normal)
    btn.setTitleColor(.black, for: .normal)
    btn.backgroundColor = .white
    btn.frame = CGRect(x: 0, y: 0, width: 110, height: 60)
    btn.center = CGPoint(x: UIScreen.main.bounds.width/2, y: UIScreen.main.bounds.height*0.90)
    btn.layer.cornerRadius = btn.bounds.height/2
    btn.tag = 0
    return btn
}()

// Pause UIButton. This button will pause a video recording.
var pauseButton:UIButton = {
    let btn = UIButton(type: .system)
    btn.setTitle("Pause", for: .normal)
    btn.setTitleColor(.black, for: .normal)
    btn.backgroundColor = .white
    btn.frame = CGRect(x: 0, y: 0, width: 60, height: 60)
    btn.center = CGPoint(x: UIScreen.main.bounds.width*0.15, y: UIScreen.main.bounds.height*0.90)
    btn.layer.cornerRadius = btn.bounds.height/2
    btn.alpha = 0.3
    btn.isEnabled = false
    return btn
}()

// GIF UIButton. This button will capture a GIF image.
var gifButton:UIButton = {
    let btn = UIButton(type: .system)
    btn.setTitle("GIF", for: .normal)
    btn.setTitleColor(.black, for: .normal)
    btn.backgroundColor = .white
    btn.frame = CGRect(x: 0, y: 0, width: 60, height: 60)
    btn.center = CGPoint(x: UIScreen.main.bounds.width*0.85, y: UIScreen.main.bounds.height*0.90)
    btn.layer.cornerRadius = btn.bounds.height/2
    return btn
}()

將按鈕添加爲視圖控制器的子視圖。在viewDidLoad()方法中插入以下代碼行:

self.view.addSubview(recorderButton)
self.view.addSubview(pauseButton)
self.view.addSubview(gifButton)

分別爲按鈕創建三個方法:

// Record and stop method
@objc func recorderAction(sender:UIButton) {
        
}
// Pause and resume method  
@objc func pauseAction(sender:UIButton) {
    
}
// Capture GIF method
@objc func gifAction(sender:UIButton) {

}

然後將方法綁定到按鈕上

recorderButton.addTarget(self, action: #selector(recorderAction(sender:)), for: .touchUpInside)
pauseButton.addTarget(self, action: #selector(pauseAction(sender:)), for: .touchUpInside)
gifButton.addTarget(self, action: #selector(gifAction(sender:)), for: .touchUpInside)

在真實設備上運行目前到程序,效果如下圖:

arkit-demo-withbutton

 

Step 3:實現ARVideoKit框架

在ViewController.swift中實現ARVideoKit框架。

首先導入框架:

import ARVideoKit

接下來,創建RecordAR類型的變量。RecordAR是ARView到子類,它使用設備的攝像頭流呈現ARSCNView或ARSKView內容,以生成視頻、照片、Live Photos或GIF。

var recorder: RecordAR?

在viewDidLoad()方法中,用ARSKView初始化RecordAR並指定支持的方向:

// Initialize with SpriteKit scene
recorder = RecordAR(ARSpriteKit: sceneView)

// Specifiy supported orientations
recorder?.inputViewOrientations = [.portrait, .landscapeLeft, .landscapeRight]

要準備recorder,需要在viewWillAppear(_ animated: Bool)方法中插入以下語句:

recorder?.prepare(configuration)

在viewWillDisappear(_ animated: Bool)方法中插入以下代碼行實現‘rest’ recorder

recorder?.rest()

Step 4:實現暫停/播放功能

檢查錄像機狀態是否準備好錄製,若準備好則開始錄製ARKit場景的視頻。否則,如果recorder正在錄製或處於暫停狀態,應用程序將停止錄像機,並將錄製好的視頻導出到相機膠捲。方法如下:

@objc func recorderAction(sender:UIButton) {
    
    if recorder?.status == .readyToRecord {
        // Start recording
        recorder?.record()
        
        // Change button title
        sender.setTitle("Stop", for: .normal)
        sender.setTitleColor(.red, for: .normal)
        
        // Enable Pause button
        pauseButton.alpha = 1
        pauseButton.isEnabled = true
        
        // Disable GIF button
        gifButton.alpha = 0.3
        gifButton.isEnabled = false
    }else if recorder?.status == .recording || recorder?.status == .paused {
        // Stop recording and export video to camera roll
        recorder?.stopAndExport()
        
        // Change button title
        sender.setTitle("Record", for: .normal)
        sender.setTitleColor(.black, for: .normal)
        
        // Enable GIF button
        gifButton.alpha = 1
        gifButton.isEnabled = true
        
        // Disable Pause button
        pauseButton.alpha = 0.3
        pauseButton.isEnabled = false
    }
    
}

接下來,在pauseAction(sender:UIButton)方法中實現暫停/恢復功能:

@objc func pauseAction(sender:UIButton) {
    if recorder?.status == .recording {
        // Pause recording
        recorder?.pause()
        
        // Change button title
        sender.setTitle("Resume", for: .normal)
        sender.setTitleColor(.blue, for: .normal)
    } else if recorder?.status == .paused {
        // Resume recording
        recorder?.record()
        
        // Change button title
        sender.setTitle("Pause", for: .normal)
        sender.setTitleColor(.black, for: .normal)
    }
}

確保在應用程序的Info.plist中添加相機、麥克風和照片庫的使用說明。

<key>NSCameraUsageDescription</key>
<string>AR Camera</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Export AR Media</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Export AR Media</string>
<key>NSMicrophoneUsageDescription</key>
<string>Audiovisual Recording</string>

 

生成GIF圖

更新gification方法:

@objc func gifAction(sender:UIButton) {
        self.gifButton.isEnabled = false
        self.gifButton.alpha = 0.3
        self.recorderButton.isEnabled = false
        self.recorderButton.alpha = 0.3

        recorder?.gif(forDuration: 1.5, export: true) { _, _, _ , exported in
            if exported {
                DispatchQueue.main.sync {
                    self.gifButton.isEnabled = true
                    self.gifButton.alpha = 1.0
                    self.recorderButton.isEnabled = true
                    self.recorderButton.alpha = 1.0
                }
            }
        }
    }

 

Step 5:修改SpriteKit內容

修改SpriteKit內容展示一些不同emojis AR space????。

先創建一個變量,該變量從一組表情符號中隨機返回一個表情符號。通過使用基於c的arc4random_uniform()函數,我們將能夠檢索一個隨機數。ViewController類中創建以下變量作爲全局變量(放置在gifButton之後):

var randoMoji: String {
    let emojis = ["?", "?", "?", "?", "?", "?", "?", "?", "?", "?"]
    return emojis[Int(arc4random_uniform(UInt32(emojis.count)))]
}

編輯方法view(_ view: ARSKView, nodeFor anchor: ARAnchor) -> SKNode?:

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: randoMoji)
    labelNode.horizontalAlignmentMode = .center
    labelNode.verticalAlignmentMode = .center
    return labelNode;
}

只需用新創建的randoMoji替換SKLabelNode的靜態文本。

 

接下來運行測試即可,實現效果如下圖:

ARKit+SpriteKit-GIF

 

參考資料:https://www.appcoda.com/record-arkit-video/

 

------AR Portal(AR開發者社區)整理

關注微信公衆號(AR開發者交流社區,提供AR開發乾貨,推動AR內容發展):AR開發者社區

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章