Spaces:
Running
Running
| import AVFoundation | |
| import Commander | |
| import Foundation | |
| import Speech | |
| import Swabble | |
| struct TranscribeCommand: ParsableCommand { | |
| (help: "Path to audio/video file") var inputFile: String = "" | |
| (name: .long("locale"), help: "Locale identifier", parsing: .singleValue) var locale: String = Locale.current | |
| .identifier | |
| (help: "Censor etiquette-sensitive content") var censor: Bool = false | |
| (name: .long("output"), help: "Output file path") var outputFile: String? | |
| (name: .long("format"), help: "Output format txt|srt") var format: String = "txt" | |
| (name: .long("max-length"), help: "Max sentence length for srt") var maxLength: Int = 40 | |
| static var commandDescription: CommandDescription { | |
| CommandDescription( | |
| commandName: "transcribe", | |
| abstract: "Transcribe a media file locally") | |
| } | |
| init() {} | |
| init(parsed: ParsedValues) { | |
| self.init() | |
| if let positional = parsed.positional.first { inputFile = positional } | |
| if let loc = parsed.options["locale"]?.last { locale = loc } | |
| if parsed.flags.contains("censor") { censor = true } | |
| if let out = parsed.options["output"]?.last { outputFile = out } | |
| if let fmt = parsed.options["format"]?.last { format = fmt } | |
| if let len = parsed.options["maxLength"]?.last, let intVal = Int(len) { maxLength = intVal } | |
| } | |
| mutating func run() async throws { | |
| let fileURL = URL(fileURLWithPath: inputFile) | |
| let audioFile = try AVAudioFile(forReading: fileURL) | |
| let outputFormat = OutputFormat(rawValue: format) ?? .txt | |
| let transcriber = SpeechTranscriber( | |
| locale: Locale(identifier: locale), | |
| transcriptionOptions: censor ? [.etiquetteReplacements] : [], | |
| reportingOptions: [], | |
| attributeOptions: outputFormat.needsAudioTimeRange ? [.audioTimeRange] : []) | |
| let analyzer = SpeechAnalyzer(modules: [transcriber]) | |
| try await analyzer.start(inputAudioFile: audioFile, finishAfterFile: true) | |
| var transcript: AttributedString = "" | |
| for try await result in transcriber.results { | |
| transcript += result.text | |
| } | |
| let output = outputFormat.text(for: transcript, maxLength: maxLength) | |
| if let path = outputFile { | |
| try output.write(to: URL(fileURLWithPath: path), atomically: false, encoding: .utf8) | |
| } else { | |
| print(output) | |
| } | |
| } | |
| } | |