iOS(swift) 自定義慢動作(slow-mo)相機

使用框架:AVFoundation

實現(xiàn)步驟

1、設(shè)置FPS:采集的視頻有要求的話,這一步是必須的;FPS默認30。這里采用最大FPS:240。

captureSession.beginConfiguration() ?? ?

captureSession.sessionPreset = .hd1280x720?

?var bestFormat: AVCaptureDevice.Format? ? ?

var maxRate: AVFrameRateRange? ? ?

for format in device.formats { ? ? ?

????for range in format.videoSupportedFrameRateRanges { ? ? ? ?

????????if maxRate?.maxFrameRate ?? 0 < range.maxFrameRate { ? ? ? ?

? ? ? ? ? ? ?maxRate = range ? ? ? ? ?

????????????bestFormat = format ? ? ? ?

????????} ? ? ?

????} ? ?

} ?? ? ? ?

if let bestFormat = bestFormat, let maxRange = maxRate { ? ? ?

????do { ? ? ? ?

????????try device.lockForConfiguration() ? ? ? ?

????????device.activeFormat = bestFormat ?? ? ? ? ? ? ? ?

????????let duration = maxRange.minFrameDuration ? ? ? ?

????????device.activeVideoMaxFrameDuration = duration ? ? ? ?

????????device.activeVideoMinFrameDuration = duration ? ? ? ?

????????device.unlockForConfiguration() ? ? ?

????} catch { ? ? ? ?

????????print(error.localizedDescription) ? ? ?

????} ? ?

} ?? ? ? ?

captureSession.commitConfiguration()

注意:

????修改activeFormat需要使用方法device.lockForConfiguration(),否則會crash;

? ? 不同F(xiàn)PS,支持的分辨率也不同,240的FPS只有分辨率1280x720支持:sessionPreset = .hd1280x720 ;

? ? 修改device參數(shù),需要更新session,否則修改無效:captureSession.commitConfiguration()。

2、視頻錄制:使用系統(tǒng)類AVCaptureMovieFileOutput,當然,也可以自己寫writer。

// 添加output,如果自己寫writer,或者實時處理buffer,需要用AVCaptureVideoDataOutput

let movieFileOutput = AVCaptureMovieFileOutput()

if captureSession.canAddOutput(movieFileOutput) { ? ?

????captureSession.addOutput(movieFileOutput) ? ? ?

????if let connection = movieFileOutput.connection(with: .video) { ? ? ? ????????

????????captureSession.beginConfiguration() ? ? ?

????????if connection.isVideoStabilizationSupported { ? ? ? ? ?

????????????connection.preferredVideoStabilizationMode = .auto ? ? ? ?

????????} ? ? ? ?

????????if connection.isVideoOrientationSupported { ? ? ? ? ?

????????????connection.videoOrientation = .landscapeRight ? ? ? ?

????????} ? ? ? ?

????????captureSession.commitConfiguration() ? ?

????}

}

// ? ?代理

func fileOutput(_ output: AVCaptureFileOutput, didStartRecordingTo fileURL: URL, from connections: [AVCaptureConnection]) {} ? ?

func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {}

3、視頻壓縮:將FPS壓縮8倍(240->30)。

guard let track = videoAsset.tracks(withMediaType: .video).first else { ? ? ?

????errorCallback?("讀取視頻信息失敗") ? ? ?

????return ? ?

} ?? ? ? ?

let mixComposition = AVMutableComposition() ? ?

let duration = videoAsset.duration ?? ? ? ?

guard ? ? ?

????let composTrack = mixComposition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid), ? ? ?

????let _ = try? composTrack.insertTimeRange(CMTimeRangeMake(start: .zero, duration: duration), of: track, at: .zero) ? ?

????else { ? ? ?

????????errorCallback?("讀取視頻信息失敗") ? ? ?

????????return ? ?

????} ?? ? ? ?

let factor = 8 ?? ? ? ?

composTrack.scaleTimeRange(CMTimeRangeMake(start: .zero, duration: duration), ?toDuration: CMTimeMake(value: duration.value * Int64(factor), timescale: duration.timescale)) ?? ? ? ?

guard let export = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPreset1280x720) else { ? ? ?

????errorCallback?("讀取視頻信息失敗") ? ? ?

????return ? ?

} ?? ? ? ?

let outURL = URL(fileURLWithPath: NSTemporaryDirectory() + "temp_compose.mp4") ? ?

try? FileManager.default.removeItem(at: outURL) ?? ? ? ?

export.outputURL = outURL ? ?

export.outputFileType = AVFileType.mp4 ? ?

export.shouldOptimizeForNetworkUse = true ?? ? ? ?

weak var weakSelf = self ? ?

export.exportAsynchronously { ? ? ?

????DispatchQueue.main.async { ? ? ? ?

? ? ? ? ? ?if export.status == .completed {

? ? ? ? ? ? ? ? //outURL

????????????}

?????} ? ?

}

注意:export回調(diào)中,進度是沒有的,需要自行獲取

4、獲取壓縮進度:

let timer = Timer(timeInterval: 0.1, repeats: true) { (_) in ? ? ?

????weakSelf?.trackCallback?(export.progress) ? ?

} ? ?

RunLoop.main.add(timer, forMode: .common)

總結(jié):

實現(xiàn)很簡單,都是很成熟的API,github上也有幾個現(xiàn)成的開源項目,想學(xué)習(xí)的可以手動實現(xiàn)一下。

參考地址:

1:?How to do Slow Motion video in IOS;

2:?Handling Frame Drops with AVCaptureVideoDataOutput。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容