implement ChunkedRecorder

- save initialization and data chunks as individual files
- ChunkType identifies chunks as initialization or data chunks
- add onChunkReady callback to ChunkedRecorder
This commit is contained in:
Rui Rodrigues 2024-07-15 08:46:41 +01:00
parent d9a1287b68
commit 89ecb35616
2 changed files with 36 additions and 19 deletions

View File

@ -12,14 +12,24 @@ import AVFoundation
class ChunkedRecorder: NSObject {
enum ChunkType {
case initialization
case data(index: UInt64)
}
struct Chunk {
let url: URL
let type: ChunkType
}
let outputURL: URL
let onChunkReady: ((Chunk) -> Void)
private var initSegment: Data?
private var index: Int = 0
private var index: UInt64 = 0
init(url: URL) throws {
init(url: URL, onChunkReady: @escaping ((Chunk) -> Void)) throws {
outputURL = url
self.onChunkReady = onChunkReady
guard FileManager.default.fileExists(atPath: outputURL.path) else {
throw CameraError.unknown(message: "output directory does not exist at: \(outputURL.path)", cause: nil)
}
@ -45,26 +55,31 @@ extension ChunkedRecorder: AVAssetWriterDelegate {
}
private func saveInitSegment(_ data: Data) {
initSegment = data
let url = outputURL.appendingPathComponent("init.mp4")
save(data: data, url: url)
onChunkReady(url: url, type: .initialization)
}
private func saveSegment(_ data: Data) {
guard let initSegment else {
print("missing init segment")
return
}
let file = String(format: "%06d.mp4", index)
defer {
index += 1
let url = outputURL.appendingPathComponent(file)
}
let name = String(format: "%06d.mp4", index)
let url = outputURL.appendingPathComponent(name)
save(data: data, url: url)
onChunkReady(url: url, type: .data(index: index))
}
private func save(data: Data, url: URL) {
do {
let outputData = initSegment + data
try outputData.write(to: url)
print("writing", data.count, "to", url)
try data.write(to: url)
} catch {
print("Error--->", error)
ReactLogger.log(level: .error, message: "Unable to write \(url): \(error.localizedDescription)")
}
}
private func onChunkReady(url: URL, type: ChunkType) {
onChunkReady(Chunk(url: url, type: type))
}
}

View File

@ -78,7 +78,9 @@ class RecordingSession {
completionHandler = completion
do {
recorder = try ChunkedRecorder(url: url.deletingLastPathComponent())
recorder = try ChunkedRecorder(url: url.deletingLastPathComponent()) { segment in
ReactLogger.log(level: .info, message: "Chunk ready: \(segment)")
}
assetWriter = AVAssetWriter(contentType: UTType(fileType.rawValue)!)
assetWriter.shouldOptimizeForNetworkUse = false
assetWriter.outputFileTypeProfile = .mpeg4AppleHLS