fix: Asset Writer Video-Audio Sync (#1075)
* fix: Start asset writer session on first frame * fix: Remove debug log * fix: Reset dev team
This commit is contained in:
		@@ -324,7 +324,7 @@ PODS:
 | 
				
			|||||||
    - React
 | 
					    - React
 | 
				
			||||||
  - RNVectorIcons (8.1.0):
 | 
					  - RNVectorIcons (8.1.0):
 | 
				
			||||||
    - React-Core
 | 
					    - React-Core
 | 
				
			||||||
  - VisionCamera (2.13.0):
 | 
					  - VisionCamera (2.13.3):
 | 
				
			||||||
    - React
 | 
					    - React
 | 
				
			||||||
    - React-callinvoker
 | 
					    - React-callinvoker
 | 
				
			||||||
    - React-Core
 | 
					    - React-Core
 | 
				
			||||||
@@ -504,7 +504,7 @@ SPEC CHECKSUMS:
 | 
				
			|||||||
  RNScreens: 40a2cb40a02a609938137a1e0acfbf8fc9eebf19
 | 
					  RNScreens: 40a2cb40a02a609938137a1e0acfbf8fc9eebf19
 | 
				
			||||||
  RNStaticSafeAreaInsets: 6103cf09647fa427186d30f67b0f5163c1ae8252
 | 
					  RNStaticSafeAreaInsets: 6103cf09647fa427186d30f67b0f5163c1ae8252
 | 
				
			||||||
  RNVectorIcons: 31cebfcf94e8cf8686eb5303ae0357da64d7a5a4
 | 
					  RNVectorIcons: 31cebfcf94e8cf8686eb5303ae0357da64d7a5a4
 | 
				
			||||||
  VisionCamera: 9959a41d3edc36b37e8361a2e6cbc05714f0689b
 | 
					  VisionCamera: 7bcf3a81533a1c9ad13930804377ad13a03fcded
 | 
				
			||||||
  Yoga: e7dc4e71caba6472ff48ad7d234389b91dadc280
 | 
					  Yoga: e7dc4e71caba6472ff48ad7d234389b91dadc280
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PODFILE CHECKSUM: 29b1752e05601e9867644e58ce0ed8b9106be6cb
 | 
					PODFILE CHECKSUM: 29b1752e05601e9867644e58ce0ed8b9106be6cb
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -456,7 +456,7 @@
 | 
				
			|||||||
				COPY_PHASE_STRIP = NO;
 | 
									COPY_PHASE_STRIP = NO;
 | 
				
			||||||
				ENABLE_STRICT_OBJC_MSGSEND = YES;
 | 
									ENABLE_STRICT_OBJC_MSGSEND = YES;
 | 
				
			||||||
				ENABLE_TESTABILITY = YES;
 | 
									ENABLE_TESTABILITY = YES;
 | 
				
			||||||
				"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 ";
 | 
									"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
 | 
				
			||||||
				GCC_C_LANGUAGE_STANDARD = gnu99;
 | 
									GCC_C_LANGUAGE_STANDARD = gnu99;
 | 
				
			||||||
				GCC_DYNAMIC_NO_PIC = NO;
 | 
									GCC_DYNAMIC_NO_PIC = NO;
 | 
				
			||||||
				GCC_NO_COMMON_BLOCKS = YES;
 | 
									GCC_NO_COMMON_BLOCKS = YES;
 | 
				
			||||||
@@ -517,7 +517,7 @@
 | 
				
			|||||||
				COPY_PHASE_STRIP = YES;
 | 
									COPY_PHASE_STRIP = YES;
 | 
				
			||||||
				ENABLE_NS_ASSERTIONS = NO;
 | 
									ENABLE_NS_ASSERTIONS = NO;
 | 
				
			||||||
				ENABLE_STRICT_OBJC_MSGSEND = YES;
 | 
									ENABLE_STRICT_OBJC_MSGSEND = YES;
 | 
				
			||||||
				"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 ";
 | 
									"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
 | 
				
			||||||
				GCC_C_LANGUAGE_STANDARD = gnu99;
 | 
									GCC_C_LANGUAGE_STANDARD = gnu99;
 | 
				
			||||||
				GCC_NO_COMMON_BLOCKS = YES;
 | 
									GCC_NO_COMMON_BLOCKS = YES;
 | 
				
			||||||
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
 | 
									GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -140,9 +140,9 @@ extension CameraView: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAud
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      // start recording session with or without audio.
 | 
					      // start recording session with or without audio.
 | 
				
			||||||
      do {
 | 
					      do {
 | 
				
			||||||
        try recordingSession.start()
 | 
					        try recordingSession.startAssetWriter()
 | 
				
			||||||
      } catch let error as NSError {
 | 
					      } 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
 | 
					        return
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      self.isRecording = true
 | 
					      self.isRecording = true
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,6 +32,7 @@ class RecordingSession {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  private var initialTimestamp: CMTime?
 | 
					  private var initialTimestamp: CMTime?
 | 
				
			||||||
  private var latestTimestamp: CMTime?
 | 
					  private var latestTimestamp: CMTime?
 | 
				
			||||||
 | 
					  private var hasStartedWritingSession = false
 | 
				
			||||||
  private var hasWrittenFirstVideoFrame = false
 | 
					  private var hasWrittenFirstVideoFrame = false
 | 
				
			||||||
  private var isFinishing = false
 | 
					  private var isFinishing = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -111,7 +112,7 @@ class RecordingSession {
 | 
				
			|||||||
  /**
 | 
					  /**
 | 
				
			||||||
   Start the Asset Writer(s). If the AssetWriter failed to start, an error will be thrown.
 | 
					   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)...")
 | 
					    ReactLogger.log(level: .info, message: "Starting Asset Writer(s)...")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let success = assetWriter.startWriting()
 | 
					    let success = assetWriter.startWriting()
 | 
				
			||||||
@@ -119,10 +120,6 @@ class RecordingSession {
 | 
				
			|||||||
      ReactLogger.log(level: .error, message: "Failed to start Asset Writer(s)!")
 | 
					      ReactLogger.log(level: .error, message: "Failed to start Asset Writer(s)!")
 | 
				
			||||||
      throw RecordingSessionError.failedToStartSession
 | 
					      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.")
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
@@ -138,11 +135,6 @@ class RecordingSession {
 | 
				
			|||||||
      ReactLogger.log(level: .error, message: "Frame arrived, but sample buffer is not ready!")
 | 
					      ReactLogger.log(level: .error, message: "Frame arrived, but sample buffer is not ready!")
 | 
				
			||||||
      return
 | 
					      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
 | 
					    latestTimestamp = timestamp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -161,10 +153,15 @@ class RecordingSession {
 | 
				
			|||||||
        ReactLogger.log(level: .error, message: "Failed to get the CVImageBuffer!")
 | 
					        ReactLogger.log(level: .error, message: "Failed to get the CVImageBuffer!")
 | 
				
			||||||
        return
 | 
					        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)
 | 
					      bufferAdaptor.append(imageBuffer, withPresentationTime: timestamp)
 | 
				
			||||||
      if !hasWrittenFirstVideoFrame {
 | 
					      if !hasWrittenFirstVideoFrame {
 | 
				
			||||||
        hasWrittenFirstVideoFrame = true
 | 
					        hasWrittenFirstVideoFrame = true
 | 
				
			||||||
        ReactLogger.log(level: .warning, message: "VideoWriter: First frame arrived \((initialTimestamp - timestamp).seconds) seconds late.")
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    case .audio:
 | 
					    case .audio:
 | 
				
			||||||
      guard let audioWriter = audioWriter else {
 | 
					      guard let audioWriter = audioWriter else {
 | 
				
			||||||
@@ -174,7 +171,7 @@ class RecordingSession {
 | 
				
			|||||||
      if !audioWriter.isReadyForMoreMediaData {
 | 
					      if !audioWriter.isReadyForMoreMediaData {
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      if !hasWrittenFirstVideoFrame {
 | 
					      if !hasWrittenFirstVideoFrame || !hasStartedWritingSession {
 | 
				
			||||||
        // first video frame has not been written yet, so skip this audio frame.
 | 
					        // first video frame has not been written yet, so skip this audio frame.
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user