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:
parent
d9a1287b68
commit
89ecb35616
@ -12,14 +12,24 @@ import AVFoundation
|
|||||||
|
|
||||||
class ChunkedRecorder: NSObject {
|
class ChunkedRecorder: NSObject {
|
||||||
|
|
||||||
|
enum ChunkType {
|
||||||
|
case initialization
|
||||||
|
case data(index: UInt64)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Chunk {
|
||||||
|
let url: URL
|
||||||
|
let type: ChunkType
|
||||||
|
}
|
||||||
|
|
||||||
let outputURL: URL
|
let outputURL: URL
|
||||||
|
let onChunkReady: ((Chunk) -> Void)
|
||||||
|
|
||||||
private var initSegment: Data?
|
private var index: UInt64 = 0
|
||||||
private var index: Int = 0
|
|
||||||
|
|
||||||
init(url: URL) throws {
|
init(url: URL, onChunkReady: @escaping ((Chunk) -> Void)) throws {
|
||||||
outputURL = url
|
outputURL = url
|
||||||
|
self.onChunkReady = onChunkReady
|
||||||
guard FileManager.default.fileExists(atPath: outputURL.path) else {
|
guard FileManager.default.fileExists(atPath: outputURL.path) else {
|
||||||
throw CameraError.unknown(message: "output directory does not exist at: \(outputURL.path)", cause: nil)
|
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) {
|
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) {
|
private func saveSegment(_ data: Data) {
|
||||||
guard let initSegment else {
|
defer {
|
||||||
print("missing init segment")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let file = String(format: "%06d.mp4", index)
|
|
||||||
index += 1
|
index += 1
|
||||||
let url = outputURL.appendingPathComponent(file)
|
|
||||||
|
|
||||||
do {
|
|
||||||
let outputData = initSegment + data
|
|
||||||
try outputData.write(to: url)
|
|
||||||
print("writing", data.count, "to", url)
|
|
||||||
} catch {
|
|
||||||
print("Error--->", error)
|
|
||||||
}
|
}
|
||||||
|
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 {
|
||||||
|
try data.write(to: url)
|
||||||
|
} catch {
|
||||||
|
ReactLogger.log(level: .error, message: "Unable to write \(url): \(error.localizedDescription)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func onChunkReady(url: URL, type: ChunkType) {
|
||||||
|
onChunkReady(Chunk(url: url, type: type))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,9 @@ class RecordingSession {
|
|||||||
completionHandler = completion
|
completionHandler = completion
|
||||||
|
|
||||||
do {
|
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 = AVAssetWriter(contentType: UTType(fileType.rawValue)!)
|
||||||
assetWriter.shouldOptimizeForNetworkUse = false
|
assetWriter.shouldOptimizeForNetworkUse = false
|
||||||
assetWriter.outputFileTypeProfile = .mpeg4AppleHLS
|
assetWriter.outputFileTypeProfile = .mpeg4AppleHLS
|
||||||
|
Loading…
Reference in New Issue
Block a user