[iOSアプリ開発!] swift2xAVFoundationxPhotoKit で動画の撮影&保存してみた

Swift2 においてAVFoundationによる動画撮影&保存方法について
sampleコードを共有しておきます。

import UIKit
import AVKit
import AVFoundation
import Photos

class ViewController: UIViewController,AVCaptureFileOutputRecordingDelegate{

private var isRecording = false
private var movieFileOutput:AVCaptureMovieFileOutput? = nil

var input:AVCaptureDeviceInput!
var output:AVCaptureMovieFileOutput!

private var myButtonStart : UIButton!

private var myButtonStop : UIButton!

var session:AVCaptureSession!
var preView:UIView!
var camera:AVCaptureDevice!

override func viewDidLoad() {
super.viewDidLoad()

myButtonStart = UIButton(frame: CGRectMake(0,0,120,50))
myButtonStop = UIButton(frame: CGRectMake(0,0,120,50))

myButtonStart.backgroundColor = UIColor.redColor();
myButtonStop.backgroundColor = UIColor.grayColor();

myButtonStart.layer.masksToBounds = true
myButtonStop.layer.masksToBounds = true

myButtonStart.setTitle("撮影", forState: .Normal)
myButtonStop.setTitle("停止", forState: .Normal)

myButtonStart.layer.cornerRadius = 20.0
myButtonStop.layer.cornerRadius = 20.0

myButtonStart.layer.position = CGPoint(x: self.view.bounds.width/2 - 70, y:self.view.bounds.height-50)
myButtonStop.layer.position = CGPoint(x: self.view.bounds.width/2 + 70, y:self.view.bounds.height-50)

myButtonStart.addTarget(self, action: "onClickMyButton:", forControlEvents: .TouchUpInside)
myButtonStop.addTarget(self, action: "onClickMyButton:", forControlEvents: .TouchUpInside)

self.view.addSubview(myButtonStart);
self.view.addSubview(myButtonStop);
}

override func viewWillAppear(animated: Bool) {
// スクリーン設定
setupDisplay()
// カメラの設定
setupCamera()
}
override func viewDidDisappear(animated: Bool) {
session.stopRunning()

for output in session.outputs{
session.removeOutput(output as? AVCaptureOutput)
}

for input in session.inputs{
session.removeInput(input as? AVCaptureInput)
}
session = nil
camera = nil
}

func setupDisplay(){
let screenWidth = UIScreen.mainScreen().bounds.size.width;
let screenHeight = UIScreen.mainScreen().bounds.size.height;

preView = UIView(frame: CGRectMake(0.0,0.0,screenWidth,screenHeight*2/3))
}

func setupCamera(){
session = AVCaptureSession()
for captureDevice:AnyObject in AVCaptureDevice.devices(){
if captureDevice.position == AVCaptureDevicePosition.Back{
camera = captureDevice as? AVCaptureDevice
}
}

do{
input = try AVCaptureDeviceInput(device: camera) as AVCaptureDeviceInput
}catch let error as NSError{
print(error)
}

if(session.canAddInput(input)){
session.addInput(input)
}

output = AVCaptureMovieFileOutput()

if(session.canAddOutput(output)){
session.addOutput(output)
}

let previewLayer = AVCaptureVideoPreviewLayer(session: session)
previewLayer.frame = preView.frame
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill

self.view.layer.addSublayer(previewLayer)

session.startRunning()

}

internal func onClickMyButton(sender:UIButton){
if(sender == myButtonStart){
self.startRecordingVideo()
}else{
self.stopRecordingVideo()
}
}

func captureOutput(captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAtURL outputFileURL: NSURL!, fromConnections connections: [AnyObject]!, error: NSError!) {
self.saveFile(outputFileURL)
}
func captureOutput(captureOutput: AVCaptureFileOutput!, didStartRecordingToOutputFileAtURL fileURL: NSURL!, fromConnections connections: [AnyObject]!) {
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}

func startRecordingVideo() {
if self.isRecording == false {
self.isRecording = true
output.startRecordingToOutputFileURL(createTempFileURL(), recordingDelegate: self)
print("STARTED RECORDING VIDEO.")
}
}

func stopRecordingVideo(){
if self.isRecording == true {
self.isRecording = false
output.stopRecording()
print("STOPPED RECORDING VIDEO.")
}
}

func createTempFileURL() -> NSURL {
var path:String = ""
let fm = NSFileManager.defaultManager()
var i = 0
while(path == "" || fm.fileExistsAtPath(path)) {
path = "\(NSTemporaryDirectory())output-\(i).mov"
i++
}
return NSURL(fileURLWithPath: path)
}

func saveFile(fileURL: NSURL) {
let library = PHPhotoLibrary.sharedPhotoLibrary()
library.performChanges({
PHAssetChangeRequest.creationRequestForAssetFromVideoAtFileURL(fileURL)
}, completionHandler: {(result: Bool, error: NSError?) -> () in
print("VIDEO FILE SAVED.")
})
}

}

注意点としては、ios9からALAssetsLibraryの使用は非推奨となったので、PHPhotoLibaryを使って保存するようにします。

参考にしたサイト
1: http://codegur.com/34427360/ios-9-swift-2-how-do-i-save-video-in-the-landscape-orientation-to-the-video-r

2: https://sites.google.com/a/gclue.jp/swift-docs/