web-dev-qa-db-ja.com

Swift AVCaptureVideoDataOutputまたはAVCaptureMovieFileOutputを使用してビデオをキャプチャする

UIImagePickerを使用せずにビデオをキャプチャする方法についてのガイダンスが必要です。ビデオはボタンクリックで開始および停止する必要があり、このデータはNSDocumentDirectoryに保存されます。私はSwiftに慣れていないので、どんな助けでも役に立ちます。

私が助けを必要としているコードのセクションは、ビデオセッションを開始および停止し、それをデータに変換することです。 captureStillImageAsynchronouslyFromConnectionを実行し、このデータをNSDocumentDirectoryに保存する写真撮影バージョンを作成しました。ビデオキャプチャセッションを設定し、データを保存するためのコードを用意しましたが、セッションからデータを取得する方法がわかりません。

var previewLayer : AVCaptureVideoPreviewLayer?
var captureDevice : AVCaptureDevice?
var videoCaptureOutput = AVCaptureVideoDataOutput()

let captureSession = AVCaptureSession()

override func viewDidLoad() {
    super.viewDidLoad()

    captureSession.sessionPreset = AVCaptureSessionPreset640x480
    let devices = AVCaptureDevice.devices()

    for device in devices {
        if (device.hasMediaType(AVMediaTypeVideo)) {
            if device.position == AVCaptureDevicePosition.Back {
                captureDevice = device as? AVCaptureDevice
                if captureDevice != nil {
                    beginSession()
                }
            }   
        }
    }
}

func beginSession() {
    var err : NSError? = nil
    captureSession.addInput(AVCaptureDeviceInput(device: captureDevice, error: &err))

    if err != nil {
        println("Error: \(err?.localizedDescription)")
    }

    videoCaptureOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey:kCVPixelFormatType_32BGRA]
    videoCaptureOutput.alwaysDiscardsLateVideoFrames = true

    captureSession.addOutput(videoCaptureOutput)

    previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
    self.view.layer.addSublayer(previewLayer)
    previewLayer?.frame = CGRectMake(0, 0, screenWidth, screenHeight)
    captureSession.startRunning()

    var startVideoBtn = UIButton(frame: CGRectMake(0, screenHeight/2, screenWidth, screenHeight/2))
        startVideoBtn.addTarget(self, action: "startVideo", forControlEvents: UIControlEvents.TouchUpInside)
        self.view.addSubview(startVideoBtn)

    var stopVideoBtn = UIButton(frame: CGRectMake(0, 0, screenWidth, screenHeight/2))
        stopVideoBtn.addTarget(self, action: "stopVideo", forControlEvents: UIControlEvents.TouchUpInside)
        self.view.addSubview(stopVideoBtn)
}

必要に応じて、さらにコードや説明を提供できます。

15
George Grover

最良の結果を得るには、 AV Foundationプログラミングガイド /の 静止画およびビデオメディアキャプチャ セクションをお読みください。

AVCaptureVideoDataOutputからのフレームを処理するには、AVCaptureVideoDataOutputSampleBufferDelegateプロトコルを採用するデリゲートが必要です。デリゲートのcaptureOutputメソッドは、新しいフレームが書き込まれるたびに呼び出されます。出力のデリゲートを設定するときは、コールバックを呼び出すキューも指定する必要があります。次のようになります。

let cameraQueue = dispatch_queue_create("cameraQueue", DISPATCH_QUEUE_SERIAL)
videoCaptureOutput.setSampleBufferDelegate(myDelegate, queue: cameraQueue)
captureSession.addOutput(videoCaptureOutput)

NB:ムービーをファイルに保存するだけの場合は、AVCaptureMovieFileOutputではなくAVCaptureVideoDataOutputクラスを使用することをお勧めします。その場合、キューは必要ありません。ただし、デリゲートが必要です。今回は、代わりにAVCaptureFileOutputRecordingDelegateプロトコルを採用します。 (関連するメソッドは引き続きcaptureOutputと呼ばれます。)

上記にリンクされているガイドのAVCaptureMovieFileOutputに関する部分からの抜粋を次に示します。

録音を開始する

startRecordingToOutputFileURL:recordingDelegate:を使用してQuickTimeムービーの記録を開始します。ファイルベースのURLとデリゲートを指定する必要があります。ムービーファイルの出力は既存のリソースを上書きしないため、URLは既存のファイルを識別してはなりません。また、指定した場所に書き込む権限も必要です。デリゲートはAVCaptureFileOutputRecordingDelegateプロトコルに準拠し、captureOutput:didFinishRecordingToOutputFileAtURL:fromConnections:error:メソッドを実装する必要があります。

AVCaptureMovieFileOutput *aMovieFileOutput = <#Get a movie file output#>;
NSURL *fileURL = <#A file URL that identifies the output location#>;
[aMovieFileOutput startRecordingToOutputFileURL:fileURL recordingDelegate:<#The delegate#>];

captureOutput:didFinishRecordingToOutputFileAtURL:fromConnections:error:の実装では、デリゲートは結果のムービーをCameraRollアルバムに書き込む場合があります。また、発生した可能性のあるエラーをチェックする必要があります。

15
leekaiinthesky