Skip to content

Commit

Permalink
fix: Asset Writer Video-Audio Sync (#1075)
Browse files Browse the repository at this point in the history
* fix: Start asset writer session on first frame

* fix: Remove debug log

* fix: Reset dev team
  • Loading branch information
thomas-coldwell authored Jun 11, 2022
1 parent de41f8b commit fb2156e
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 18 deletions.
4 changes: 2 additions & 2 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ PODS:
- React
- RNVectorIcons (8.1.0):
- React-Core
- VisionCamera (2.13.0):
- VisionCamera (2.13.3):
- React
- React-callinvoker
- React-Core
Expand Down Expand Up @@ -504,7 +504,7 @@ SPEC CHECKSUMS:
RNScreens: 40a2cb40a02a609938137a1e0acfbf8fc9eebf19
RNStaticSafeAreaInsets: 6103cf09647fa427186d30f67b0f5163c1ae8252
RNVectorIcons: 31cebfcf94e8cf8686eb5303ae0357da64d7a5a4
VisionCamera: 9959a41d3edc36b37e8361a2e6cbc05714f0689b
VisionCamera: 7bcf3a81533a1c9ad13930804377ad13a03fcded
Yoga: e7dc4e71caba6472ff48ad7d234389b91dadc280

PODFILE CHECKSUM: 29b1752e05601e9867644e58ce0ed8b9106be6cb
Expand Down
4 changes: 2 additions & 2 deletions example/ios/VisionCameraExample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 ";
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
Expand Down Expand Up @@ -517,7 +517,7 @@
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 ";
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
Expand Down
4 changes: 2 additions & 2 deletions ios/CameraView+RecordVideo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,9 @@ extension CameraView: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAud

// start recording session with or without audio.
do {
try recordingSession.start()
try recordingSession.startAssetWriter()
} catch let error as NSError {
callback.reject(error: .capture(.createRecorderError(message: "RecordingSession failed to start writing.")), cause: error)
callback.reject(error: .capture(.createRecorderError(message: "RecordingSession failed to start asset writer.")), cause: error)
return
}
self.isRecording = true
Expand Down
21 changes: 9 additions & 12 deletions ios/RecordingSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class RecordingSession {

private var initialTimestamp: CMTime?
private var latestTimestamp: CMTime?
private var hasStartedWritingSession = false
private var hasWrittenFirstVideoFrame = false
private var isFinishing = false

Expand Down Expand Up @@ -111,18 +112,14 @@ class RecordingSession {
/**
Start the Asset Writer(s). If the AssetWriter failed to start, an error will be thrown.
*/
func start() throws {
func startAssetWriter() throws {
ReactLogger.log(level: .info, message: "Starting Asset Writer(s)...")

let success = assetWriter.startWriting()
if !success {
ReactLogger.log(level: .error, message: "Failed to start Asset Writer(s)!")
throw RecordingSessionError.failedToStartSession
}

initialTimestamp = CMTime(seconds: CACurrentMediaTime(), preferredTimescale: 1_000_000_000)
assetWriter.startSession(atSourceTime: initialTimestamp!)
ReactLogger.log(level: .info, message: "Started RecordingSession at \(initialTimestamp!.seconds) seconds.")
}

/**
Expand All @@ -138,11 +135,6 @@ class RecordingSession {
ReactLogger.log(level: .error, message: "Frame arrived, but sample buffer is not ready!")
return
}
guard let initialTimestamp = initialTimestamp else {
ReactLogger.log(level: .error,
message: "A frame arrived, but initialTimestamp was nil. Is this RecordingSession running?")
return
}

latestTimestamp = timestamp

Expand All @@ -161,10 +153,15 @@ class RecordingSession {
ReactLogger.log(level: .error, message: "Failed to get the CVImageBuffer!")
return
}
// Start the writing session before we write the first video frame
if !hasStartedWritingSession {
assetWriter.startSession(atSourceTime: timestamp)
ReactLogger.log(level: .info, message: "Started RecordingSession at \(timestamp.seconds) seconds.")
hasStartedWritingSession = true
}
bufferAdaptor.append(imageBuffer, withPresentationTime: timestamp)
if !hasWrittenFirstVideoFrame {
hasWrittenFirstVideoFrame = true
ReactLogger.log(level: .warning, message: "VideoWriter: First frame arrived \((initialTimestamp - timestamp).seconds) seconds late.")
}
case .audio:
guard let audioWriter = audioWriter else {
Expand All @@ -174,7 +171,7 @@ class RecordingSession {
if !audioWriter.isReadyForMoreMediaData {
return
}
if !hasWrittenFirstVideoFrame {
if !hasWrittenFirstVideoFrame || !hasStartedWritingSession {
// first video frame has not been written yet, so skip this audio frame.
return
}
Expand Down

0 comments on commit fb2156e

Please sign in to comment.