Files
bsky-social-app/modules/expo-bluesky-video-compress/ios/ExpoBlueskyVideoCompressModule.swift

75 lines
2.2 KiB
Swift

import AVFoundation
import ExpoModulesCore
public class ExpoBlueskyVideoCompressModule: Module {
private var activeCompressors: [Int: VideoCompressor] = [:]
private let activeCompressorsLock = NSLock()
public func definition() -> ModuleDefinition {
Name("ExpoBlueskyVideoCompress")
Events("onProgress")
AsyncFunction("probe") { (uri: String) -> [String: Any] in
let url = URL(string: uri) ?? URL(fileURLWithPath: uri)
return try await VideoProber.probe(url: url)
}
AsyncFunction("compress") { (uri: String, options: [String: Any]) -> [String: Any] in
let url = URL(string: uri) ?? URL(fileURLWithPath: uri)
let targetBitrate = options["targetBitrate"] as? Int ?? 0
let maxSize = options["maxSize"] as? Int ?? 1920
let codecPref = options["codec"] as? String ?? "auto"
let frameRateCap = max(1, options["frameRateCap"] as? Int ?? 30)
let jobId = options["jobId"] as? Int ?? 0
let compressor = VideoCompressor(
url: url,
targetBitrate: targetBitrate,
maxSize: maxSize,
codecPref: codecPref,
frameRateCap: frameRateCap,
jobId: jobId,
onProgress: { [weak self] id, progress in
self?.sendEvent("onProgress", [
"id": id,
"progress": progress,
])
}
)
self.setCompressor(jobId, compressor)
do {
let result = try await compressor.compress()
self.setCompressor(jobId, nil)
return result
} catch {
self.setCompressor(jobId, nil)
throw error
}
}
Function("cancel") { (jobId: Int) in
self.cancelCompressor(jobId)
}
}
private func setCompressor(_ jobId: Int, _ compressor: VideoCompressor?) {
activeCompressorsLock.lock()
defer { activeCompressorsLock.unlock() }
if let compressor = compressor {
activeCompressors[jobId] = compressor
} else {
activeCompressors.removeValue(forKey: jobId)
}
}
private func cancelCompressor(_ jobId: Int) {
activeCompressorsLock.lock()
let compressor = activeCompressors.removeValue(forKey: jobId)
activeCompressorsLock.unlock()
compressor?.cancel()
}
}