使用框架: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)一下。
參考地址: