StreamRecorder/Sources/StreamRecorderKit/StreamRecorderEngine.swift

94 lines
2.9 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Foundation
///
public protocol StreamRecorderDelegate: AnyObject {
func recorderDidStart(_ recorder: StreamRecorderEngine)
func recorder(_ recorder: StreamRecorderEngine, didUpdateProgress progress: RecordingProgress)
func recorder(_ recorder: StreamRecorderEngine, didFinishWithResult result: RecordingResult)
func recorder(_ recorder: StreamRecorderEngine, didFailWithError error: Error)
}
///
public struct RecordingProgress {
public let currentTime: Double //
public let totalDuration: Double //
public let bytesWritten: Int64 //
public let bitrate: Double // (kbps)
public var percentage: Double {
guard totalDuration > 0 else { return 0 }
return min(currentTime / totalDuration * 100, 100)
}
}
///
public struct RecordingResult {
public let outputPath: String
public let duration: Double
public let fileSize: Int64
public let hasVideo: Bool
public let hasAudio: Bool
public let videoInfo: VideoInfo?
public let audioInfo: AudioInfo?
public let audioLevel: AudioLevel?
}
public struct VideoInfo {
public let codec: String
public let width: Int
public let height: Int
public let fps: Double
public let pixelFormat: String
}
public struct AudioInfo {
public let codec: String
public let sampleRate: Int
public let channels: Int
}
public struct AudioLevel {
public let meanVolume: Double // dB
public let maxVolume: Double // dB
public let isSilent: Bool
}
public enum RecordingError: Error, LocalizedError {
case invalidURL
case noFFmpeg
case noMediaTracks
case processFailed(Int, String? = nil)
case outputNotFound(String? = nil)
case unknown(String)
public var errorDescription: String? {
switch self {
case .invalidURL: return "无效的 URL"
case .noFFmpeg: return "未找到 ffmpeg请安装: brew install ffmpeg"
case .noMediaTracks: return "未找到任何媒体轨道"
case .processFailed(let code, let stderr):
if let s = stderr, !s.isEmpty {
let preview = String(s.prefix(300))
return "录制失败 (exit code: \(code)):\n\(preview)"
}
return "录制失败 (exit code: \(code))"
case .outputNotFound(let stderr):
if let s = stderr, !s.isEmpty {
let preview = String(s.prefix(300))
return "输出文件不存在\n\(preview)"
}
return "输出文件不存在"
case .unknown(let msg): return msg
}
}
}
///
public protocol StreamRecorderEngine: AnyObject {
var delegate: StreamRecorderDelegate? { get set }
var isRecording: Bool { get }
func start(url: URL, outputPath: String, duration: Double) async throws
func stop()
}