fix: Fix Video Recording delay and improve startRecording()
performance (#2192)
* fix: Add more logs * perf: Init audio AVAssetWriter in parallel * chore: Log Audio Session activation * perf: Init Audio Session asynchronously * chore: Log when category changed * fix: Revert lazy audio initialization * Update Podfile.lock * Pass `sourceFormatHint` to video and audio AVAssetWriter * fix: Remove `sourceFormatHint` from Video Asset Writer * Use default options for Audio Asset Writer * Update Podfile.lock * Revert "Use default options for Audio Asset Writer" This reverts commit e575a14c5342ddc7f9db557d5e3915328ed9e798. * Add time logs * fix: Don't synchronize audio buffers, they are already in sync * shouldOptimizeForNetworkUse = false * fix: Only update `latestTimestamp` once video buffer has been written * perf: Use `AVAssetWriterInput` instead of `AVAssetWriterInputPixelBufferAdaptor` * fix: Fix Audio not being synchronized with Video * Remove logs add comments * Format * feat: Set `.videoRecording` AVAudioSession mode * Refactor `startRecording()` a bit * Format * chore: Throw error directly instead of double-checking
This commit is contained in:
@@ -13,11 +13,14 @@ extension AVAudioSession {
|
||||
/**
|
||||
Calls [setCategory] if the given category or options are not equal to the currently set category and options.
|
||||
*/
|
||||
func updateCategory(_ category: AVAudioSession.Category, options: AVAudioSession.CategoryOptions = []) throws {
|
||||
if self.category != category || categoryOptions.rawValue != options.rawValue {
|
||||
func updateCategory(_ category: AVAudioSession.Category,
|
||||
mode: AVAudioSession.Mode,
|
||||
options: AVAudioSession.CategoryOptions = []) throws {
|
||||
if self.category != category || categoryOptions.rawValue != options.rawValue || self.mode != mode {
|
||||
ReactLogger.log(level: .info,
|
||||
message: "Changing AVAudioSession category from \(self.category.rawValue) -> \(category.rawValue)")
|
||||
try setCategory(category, options: options)
|
||||
try setCategory(category, mode: mode, options: options)
|
||||
ReactLogger.log(level: .info, message: "AVAudioSession category changed!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// AVCaptureSession+synchronizeBuffer.swift
|
||||
// VisionCamera
|
||||
//
|
||||
// Created by Marc Rousavy on 22.11.23.
|
||||
// Copyright © 2023 mrousavy. All rights reserved.
|
||||
//
|
||||
|
||||
import AVFoundation
|
||||
import Foundation
|
||||
|
||||
extension AVCaptureSession {
|
||||
private var clock: CMClock {
|
||||
if #available(iOS 15.4, *), let synchronizationClock {
|
||||
return synchronizationClock
|
||||
}
|
||||
|
||||
return masterClock ?? CMClockGetHostTimeClock()
|
||||
}
|
||||
|
||||
/**
|
||||
Synchronizes a Buffer received from this [AVCaptureSession] to the timebase of the other given [AVCaptureSession].
|
||||
*/
|
||||
func synchronizeBuffer(_ buffer: CMSampleBuffer, toSession to: AVCaptureSession) {
|
||||
let timestamp = CMSampleBufferGetPresentationTimeStamp(buffer)
|
||||
let synchronizedTimestamp = CMSyncConvertTime(timestamp, from: clock, to: to.clock)
|
||||
ReactLogger.log(level: .info, message: "Synchronized Timestamp \(timestamp.seconds) -> \(synchronizedTimestamp.seconds)")
|
||||
CMSampleBufferSetOutputPresentationTimeStamp(buffer, newValue: synchronizedTimestamp)
|
||||
}
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// AVCaptureVideoDataOutput+recommendedVideoSettings.swift
|
||||
// VisionCamera
|
||||
//
|
||||
// Created by Marc Rousavy on 22.11.23.
|
||||
// Copyright © 2023 mrousavy. All rights reserved.
|
||||
//
|
||||
|
||||
import AVFoundation
|
||||
import Foundation
|
||||
|
||||
extension AVCaptureVideoDataOutput {
|
||||
/**
|
||||
Get the recommended options for an [AVAssetWriter] with the desired [RecordVideoOptions].
|
||||
*/
|
||||
func recommendedVideoSettings(forOptions options: RecordVideoOptions) throws -> [String: Any] {
|
||||
let settings: [String: Any]?
|
||||
if let videoCodec = options.codec {
|
||||
settings = recommendedVideoSettings(forVideoCodecType: videoCodec, assetWriterOutputFileType: options.fileType)
|
||||
} else {
|
||||
settings = recommendedVideoSettingsForAssetWriter(writingTo: options.fileType)
|
||||
}
|
||||
guard var settings else {
|
||||
throw CameraError.capture(.createRecorderError(message: "Failed to get video settings!"))
|
||||
}
|
||||
|
||||
if let bitRate = options.bitRate {
|
||||
// Convert from Mbps -> bps
|
||||
let bitsPerSecond = bitRate * 1_000_000
|
||||
settings[AVVideoCompressionPropertiesKey] = [
|
||||
AVVideoAverageBitRateKey: NSNumber(value: bitsPerSecond),
|
||||
]
|
||||
}
|
||||
|
||||
return settings
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user