【问题标题】:Find silence in AVAudioRecorder Session在 AVAudioRecorder Session 中找到静音
【发布时间】:2017-09-19 10:05:44
【问题描述】:

一旦用户停止录音,我该如何停止录音? 就像 Siri。一旦你说,嗨 Siri,它就会响应你的声音。表示 Siri 应用程序一直在听音频,直到您停止录音。

我正在尝试做同样的事情。如果我说,一旦我停止声音,获取天气详细信息。我想触发一种方法或使用录制的音频调用 API 直到停止。

我的要求是应用程序应该不断听取用户发现语音结束事件发送数据到服务器或只是触发一个方法。

代码:

import UIKit
import CoreAudio
import CoreAudioKit
import AVFoundation
import Foundation
import AVKit



class ViewController: UIViewController, AVAudioRecorderDelegate {

    private var recorder    : AVAudioRecorder? = nil
    private var isRecording : Bool = false
    private var timer       : Timer? = nil

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        permissionWasGranted { (isValied) in
            print("isValied")
            self.isRecording = false;
            self.intiateTimer()

        }
    }

    @objc func intiateTimer() {
        self.timer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(self.updateTimer), userInfo: nil, repeats: true)

    }
    @objc func updateTimer() {

        if !isRecording {
            //recorder = nil
            self.initRecorder()
            print("Recording intiated")
        }
        else {
            print("Recording Started")
        }
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func getDocumentsDirectory() -> URL {
        let fileManager         = FileManager.default
        let urls                = fileManager.urls(for: .documentDirectory, in: .userDomainMask)
        let documentDirectory   = urls.first!
        return documentDirectory.appendingPathComponent("recording.m4a")
    }

    // MARK: protocol


    func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
        recorder.stop()
        recorder.deleteRecording()
        recorder.prepareToRecord()
        isRecording = false
        self.updateTimer()
    }


    func permissionWasGranted(result: @escaping (_: Bool)->()) {
        switch AVAudioSession.sharedInstance().recordPermission() {
        case AVAudioSessionRecordPermission.granted:
            //if IS_DEBUG { print("Permission granted") }
            print("Permission granted")

            result(true)
            return
        case AVAudioSessionRecordPermission.denied:
            //if IS_DEBUG { print("Pemission denied") }
                print("Pemission denied")
        case AVAudioSessionRecordPermission.undetermined:
            //if IS_DEBUG { print("Request permission here") }
            print("Request permission here")

            AVAudioSession.sharedInstance().requestRecordPermission({ (granted) in
                if granted {
                    result(true)
                    return
                }
            })

        }
        result(false)
    }

    func initRecorder() {
        let settings = [
            AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
            AVSampleRateKey: 12000,
            AVNumberOfChannelsKey: 1,
            AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
        ]
        do {
            let session = AVAudioSession.sharedInstance()
            try session.setCategory(AVAudioSessionCategoryPlayAndRecord)
            try session.overrideOutputAudioPort(AVAudioSessionPortOverride.speaker)
            try session.setActive(true)

            try recorder = AVAudioRecorder(url: getDocumentsDirectory(), settings: settings)
            recorder!.delegate = self
            recorder!.isMeteringEnabled = true

            if !recorder!.prepareToRecord() {
                print("Error: AVAudioRecorder prepareToRecord failed")
            }


            let decibels = self.getDispersyPercent()
            if decibels > -120  && decibels < -20 {
                self.timer?.invalidate()
                isRecording = true;
                self.start()
            }


        } catch {
            print("Error: AVAudioRecorder creation failed")
        }
    }

    func start() {
        recorder?.record()
        recorder?.updateMeters()
    }

    func update() {
        if let recorder = recorder {
            recorder.updateMeters()
        }
    }

    func getDispersyPercent() -> Float {
        if let recorder = recorder {
            let decibels = recorder.averagePower(forChannel: 0)
            return decibels
        }
        return 0
    }

}

【问题讨论】:

  • 你需要跟踪录音机的分贝(db)
  • 这个答案可能对您有帮助 stackoverflow.com/a/43429136/468724 。请记住,您需要触发计时器才能在特定间隔后获取值
  • 您可以使用 iOS sdk 中提供的语音合成器。它会立即将您的声音转换为文本。用于演示github.com/Gagan5278/SpeechSynthesizer
  • 我在这里添加了我的代码,谁能帮帮我。我在哪里失踪?
  • @Damodar 你有没有找到任何解决方案。我也面临同样的问题,我尝试了一些修剪技术(AVAssetExportSession),但仍然没有得到正确的输出。如果用户在特定时间段内保持沉默,我需要重置 AVAudioRecorder。如果可能的话,请告诉我。

标签: ios swift avaudiorecorder


【解决方案1】:

在这里我创建了我的函数,它实际上会检测到 5 秒的静音,如果满足条件,您可以停止记录该时间

-- 我使用了 Recording Manager NSObject 类,所以你可以从下面的函数中获取代码并设法在你的函数中使用它

代码

//StartNewRecordingIfSilenceFor5Second
    func newSessionIfSilence(){

        //get Audio file name to store
        let AudioFileName = getDocumentsDirectory().appendingPathComponent("\(getUniqueName()).wav")
        //Declare a value that will be updated when silence is detected
        var statusForDetection = Float()
        //Recorder Settings used
        let settings: [String: Any] = [
            AVFormatIDKey: Int(kAudioFormatLinearPCM),
            AVSampleRateKey: 16000,
            AVNumberOfChannelsKey: 1,
            AVLinearPCMBitDepthKey: 16,
            AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue,
            AVLinearPCMIsBigEndianKey: false,
            AVLinearPCMIsFloatKey: false,
            ]
        //Try block
        do {
            //Start Recording With Audio File name
            Manager.recorder = try AVAudioRecorder(url: AudioFileName, settings: settings)
            Manager.recorder?.delegate = self
            Manager.recorder?.isMeteringEnabled = true
            Manager.recorder?.prepareToRecord()
            Manager.recorder?.record()

            //Tracking Metering values here only
            Manager.meterTimer = Timer.scheduledTimer(withTimeInterval: 0.10, repeats: true, block: { (timer: Timer) in

                //Update Recording Meter Values so we can track voice loudness
                //Getting Recorder from another class
                //i managed my recorder from Manager class
                if let recorder = Manager.recorder
                {
                    //Start Metering Updates
                    recorder.updateMeters()

                    //Get peak values
                    Manager.recorderApc0 = recorder.averagePower(forChannel: 0)
                    Manager.recorderPeak0 = recorder.peakPower(forChannel: 0)

                    //it’s converted to a 0-1 scale, where zero is complete quiet and one is full volume.
                    let ALPHA: Double = 0.05
                    let peakPowerForChannel = pow(Double(10), (0.05 * Double(Manager.recorderPeak0)))

//                    static var lowPassResults: Double = 0.0
                    RecordingManager.lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * RecordingManager.lowPassResults

                    if(RecordingManager.lowPassResults > 0){
                        print("Mic blow detected")
                        //Do what you wanted to do here

                        //if blow is detected update silence value as zero
                        statusForDetection = 0.0
                    }
                    else
                    {

                        //Update Value for Status is blow being detected or not
                        //As timer is called at interval of 0.10 i.e 0.1 So add value each time in silence Value with 0.1
                        statusForDetection += 0.1


                        //if blow is not Detected for 5 seconds
                        if statusForDetection > 5.0 {
                            //Update value to zero
                            //When value of silence is greater than 5 Seconds
                            //Time to Stop recording
                            statusForDetection = 0.0

                            //Stop Audio recording
                            recorder.stop()

                        }
                    }
                }
            })

        } catch {
            //Finish Recording with a Error
            print("Error Handling: \(error.localizedDescription)")
            self.finishRecording(success: false)
        }

    }

【讨论】:

  • 您对 lowPassResults 的计算有点混乱。检查平均功率值(例如,如果 recorderApc0
  • 是的,实际上我将它转换为 0 到 1 的比例
  • 这不会创建无限数量的 .wav 文件吗?
  • 取决于静音 "statusForDetection" 我设置为 5.0 在每 5 秒录音后它会创建新文件
【解决方案2】:

你可以给录音机添加一个周期性的监听器(在开始录音之后),勾选recorder.averagePower(forChannel: 0)你可以处理最低级别来停止录音。

【讨论】:

  • 这个你要小心,不知道你知不知道。 0 值是最大值 返回值 正在录制的声音的当前平均功率,以分贝为单位。返回值 0 dB 表示满量程或最大功率;返回值 -160 dB 表示最小功率(即接近静音)。如果提供给录音机的信号超过±满量程,则返回值可能超过0(即可能进入正值范围)。 link
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-23
相关资源
最近更新 更多