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开发者社区

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