123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- //
- // BFVoiceRecordManager.swift
- // BFRecordScreenKit
- //
- // Created by 胡志强 on 2021/11/24.
- //
- import BFCommonKit
- import BFMediaKit
- import Foundation
- class BFVoiceRecordManager: NSObject {
-
- let debugHeader:String = "debugHeaderManger"
- // 录音相关
- var audioRecorder: BFRecorderManager?
- // 录音结束回调
- var endRecordHandle: ((PQVoiceModel?, Error?) -> Void)?
- // 录音取消回调
- var cancelRecordHandle: ((PQVoiceModel?) -> Void)?
- // 录音进度回调
- var recorderProgrossHandle: ((Float64) -> Void)?
- // 字幕的回调 参数1: 字幕数据 ,参数2 :对应的录音文件
- var subtitleRecordHandle: ((String?, String?) -> Void)?
- // 字幕服务 dubug信息
- var NeoNuiDebugHandle: ((String?) -> Void)?
- // 录音机 dubug信息
- var AudioQueueRecoderDebugHandle: ((String?) -> Void)?
-
- // 音频文件模型
- var voiceModel: PQVoiceModel?
- // 停止是否为取消操作
- var mIsCancel: Bool = false
- // 是否正在停止中,从调用停止方法,到真正停止结束大约要300ms 左右。在这个期间内如果调用在调用了 start 开始时间被重置, 就会触发< 1s的逻辑。
- var isStoping: Bool = false
- /// 初始化方法
- /// - Parameters:
- /// - token: NLS token
- /// - appid: NLS appid
- override public init() {
- super.init()
- audioRecorder = BFRecorderManager()
- audioRecorder?.delegate = self
- }
-
- deinit{
- audioRecorder?.delegate = nil
- }
-
- /// 开始录音
- func startRecord() {
- BFLog(2, message: "\(debugHeader)开始录音::: \(Date().timeIntervalSince1970)")
- if isStoping {
- AudioQueueRecoderDebugHandle?("正在停止中,这次开始无效.")
- BFLog(2, message: "\(debugHeader)正在停止中,这次开始无效.")
- return
- }
- var recorderFilePath = exportAudiosDirectory
- if !directoryIsExists(dicPath: recorderFilePath) {
- BFLog(message: "\(debugHeader)文件夹不存在 \(recorderFilePath)")
- createDirectory(path: recorderFilePath)
- }
-
- recorderFilePath.append("recorder_\(Date().timeIntervalSince1970).pcm")
-
- let noiseFilePath = recorderFilePath.replacingOccurrences(of: ".pcm", with: "_noise.wav")
- voiceModel?.wavFilePath = noiseFilePath
- BFLog(1, message: "\(debugHeader)开始录音::: \(recorderFilePath)")
- audioRecorder?.startRecord(recorderFilePath)
- }
-
- func cancelTitleService() {
- audioRecorder?.stopNui_dialog(true)
- isStoping = false
- }
- /// 停止录制
- /// - Parameter isCancel: 是否为取消 ,取消操作会把录制的文件删除和字幕删除
- func stopRecord(isCancel: Bool) {
- BFLog(2, message: "\(debugHeader)结束录音::: \(Date().timeIntervalSince1970)")
- isStoping = true
- mIsCancel = isCancel
- //停止录音机录音
- audioRecorder?.voiceRecorder.stop(true)
- //停止字幕服务
- audioRecorder?.stopNui_dialog(false)
-
- }
- }
- // MARK: - 录音机回调
- extension BFVoiceRecordManager: BFRecorderManagerDelegate {
- public func recorderProgress(_: BFRecorderManager, recoderTime: Double) {
- // BFLog(message: "录音机进度:\(recoderTime)")
- recorderProgrossHandle?(recoderTime)
- }
- public func recorderDidStop(_ outfile: String) {
- if mIsCancel {
- // 删除录制的原文件
- deleteFile(outfile: outfile)
- cancelRecordHandle?(nil)
- } else {
- var beginRecordTime1 = Date()
- // 1转wav
- let wavFilePath = outfile.replacingOccurrences(of: ".pcm", with: ".wav")
- BFPcmToWaveTool().pcmToWav(inFileName: outfile, outFileName: wavFilePath)
- BFLog(message: "\(debugHeader)转 WAV用时\(Date().timeIntervalSince(beginRecordTime1))")
- // 删除录制的原文件
- deleteFile(outfile: outfile)
- // 2处理降噪
- beginRecordTime1 = Date()
- let noiseFilePath = wavFilePath.replacingOccurrences(of: ".wav", with: "_noise.wav")
- BFLog(1, message: "\(debugHeader)降噪后地址:\(noiseFilePath) 原地址:\(wavFilePath)")
- NXNoiseReduction().denoise(wavFilePath, outFile: noiseFilePath)
- if let model = voiceModel {
- model.wavFilePath = noiseFilePath
- endRecordHandle?(model, nil)
- BFLog(message: "\(debugHeader)降噪用时\(Date().timeIntervalSince(beginRecordTime1))")
- }
- // 删除临时 wav 文件
- deleteFile(outfile: wavFilePath)
- }
-
- // 其它逻辑写在上面 保证最后关开关。
- isStoping = false
- }
- /// 删除文件
- /// - Parameter outfile: <#outfile description#>
- public func deleteFile(outfile:String) {
- if FileManager.default.fileExists(atPath: outfile) {
- do {
- try FileManager.default.removeItem(at: NSURL.fileURL(withPath: outfile))
- } catch {
- BFLog(message: "删除文件出错 == \(error) \(outfile)")
- }
- }
- }
-
- //字幕返回
- public func eventCallback(_: BFRecorderManager, asrResult: String, audioFilePath: String) {
- // 最后输出的文件是降噪后的
- let noiseFilePath = audioFilePath.replacingOccurrences(of: ".pcm", with: "_noise.wav")
- subtitleRecordHandle?(asrResult, noiseFilePath)
- }
- public func neoNuiDebugHandle(_ msg: String) {
- BFLog(2, message: "neoNuiDebugHandle :\(msg)")
- NeoNuiDebugHandle?(msg)
- }
- public func audioQueueRecoderDebugHandle(_ msg: String) {
- BFLog(2, message: "audioQueueRecoderDebugHandle :\(msg)")
- AudioQueueRecoderDebugHandle?(msg)
- }
- }
|