If you've ever tried recording audio or video from the device's camera in an iOS app, you've probably had a bad time. As always, though, somebody else's open-source code can make your life a lot easier.
Here, I'm going to show you how to use a cocoapod called SCRecorder. It's a wonderful module but it's lacking proper documentation and I couldn't find an example that uses Swift. The app we'll build will simply record videos, play them back, and save them to the camera roll.
Just a heads up: you're going to need to be able to run this on an actual iOS device to test it out.
Installing SCRecorder
First create a new Xcode project; just a simple single-view application. Then, create a file in the root of this application called Podfile
. Give it the following contents.
platform :ios, '7.0'
use_frameworks!
pod 'SCRecorder'
The next step is to boot up a new Terminal session, move into the project directory, then run the command: pod install
. If this doesn't work because you don't have cocoapods installed already, run the comand gem install cocoapods
. The pod install
command will install SCRecorder, and create a .xcworkspace
file for us; open this file from finder, or with the command open *.xcworkspace
. You must use this instead of the .xcodeproj
file from now on.
Setting Up Our View
Now in Main.storyboard
, add a UIView in the default view controller with the following constraints (you should change the dimensions of the view controller for this):
This UIView will preview the video as it records.
I'll also add four buttons, one label, and one UIView as follows. You should be able to figure out the constraints for yourself (center the buttons, and the UIView is 60pt wide/tall). The extra UIView will be where we can watch the video we have recorded.
Next, we need to add some IBActions and IBOutlets to ViewController.swift
. These should all be pretty self explanatory. The first UIView outlet listed below is the larger one.
Recording Video
We need to import SCRecorder
at the top of ViewController.swift
. We also need to add a couple of properties to this class; an instance of SCRecorder
I'll call recorder
, and an instance of SCRecordSession
I'll call session
. The SCRecordSession stores the video data, and the SCRecorder appends recording data to it.
import UIKit
import SCRecorder
class ViewController: UIViewController {
let session = SCRecordSession()
let recorder = SCRecorder()
//...
We'll configure these in viewDidLoad
and viewDidLayoutSubviews
now:
override func viewDidLoad() {
super.viewDidLoad()
if (!recorder.startRunning()) {
debugPrint("Recorder error: ", recorder.error)
}
recorder.session = session
recorder.device = AVCaptureDevicePosition.Front
recorder.videoConfiguration.size = CGSizeMake(800,800)
recorder.delegate = self
}
override func viewDidLayoutSubviews() {
recorder.previewView = previewView
}
The recorder.previewView
setting will cause the live camera feed to show in our aptly named previewView
outlet. You'll be getting an error now about ViewController
not conforming to SCRecorderDelegate
. We'll fix this with an extension so that our code stays neat. While we're at it, we'll write some code that controls the timer shown on the screen. Add the following below the ViewController
class definition:
extension ViewController: SCRecorderDelegate {
func recorder(recorder: SCRecorder, didAppendVideoSampleBufferInSession session: SCRecordSession) {
updateTimeText(session)
}
func updateTimeText(session: SCRecordSession) {
self.timeLabel.text = String(session.duration.seconds)
}
}
Finally, let's fill in our actions:
@IBAction func recordButtonPress(sender: AnyObject) {
recorder.record()
}
@IBAction func pauseButtonPress(sender: AnyObject) {
recorder.pause()
}
@IBAction func backspaceButtonPress(sender: AnyObject) {
if recorder.isRecording {
recorder.pause()
return
}
session.removeLastSegment()
updateTimeText(session)
}
With this complete, you can now record video segments, and delete the last one with the backspace button. Currently, the only feedback is the timer, so let's implement some playback.
Playing Video
ViewController
needs an SCPlayer
property and some setup code in viewDidLayoutSubview
, and we need to write the playButtonPress
action. There's one problem though: The code is as follows:
let player = SCPlayer()
@IBAction func playButtonPress(sender: AnyObject) {
player.play()
}
override func viewDidLayoutSubviews() {
recorder.previewView = previewView
player.setItemByAsset(session.assetRepresentingSegments())
let playerLayer = AVPlayerLayer(player: player)
let bounds = playbackView.bounds
playerLayer.frame = bounds
playbackView.layer.addSublayer(playerLayer)
}
This was very laggy on my phone though, having the two videos on the screen at once; sometimes the playback video wouldn't appear. You might want to comment out the first line of viewDidLayoutSubviews
while playing around.
You should have a pretty neat app at this point. Now let's save the video you record
Saving Videos
Add an extra button to ViewController with a corresponding IBAction called saveButtonPress
. The code for saveButtonPress
is as follows:
@IBAction func saveButtonPress(sender: AnyObject) {
session.mergeSegmentsUsingPreset(AVAssetExportPresetHighestQuality) { (url, error) in
if (error == nil) {
url?.saveToCameraRollWithCompletion({ (path, error) in
debugPrint(path, error)
})
} else {
debugPrint(error)
}
}
}
And that's our video-recording app done; that easy. For more details about SCRecorder, check out the github repository.