0

I'm using AVAudioEngine to record audio in my iOS app. I want to stop the recording automatically if there is no audio input for a specified duration (e.g., 5 seconds). How can I achieve this?

Here is the code I have so far for starting the recording:

 func startRecording() throws {
 guard let engine = self.audioEngine, let mic = mic else { return }
 let micFormat = mic.inputFormat(forBus: 0)
 self.state = .recording
 let startTime = DispatchTime.now()
 mic.installTap(onBus: 0, bufferSize: 4096, format: micFormat) { (buffer, when) in
 // Data(buffer: buffer, time: when)
 let sampleData = UnsafeBufferPointer(start: buffer.floatChannelData![0], count: Int(buffer.frameLength))
 // print(buffer)
 let currentTime = DispatchTime.now()
 let elapsedTime = currentTime.uptimeNanoseconds - startTime.uptimeNanoseconds
 let timeout = 5
 let isFinal = elapsedTime > timeout * 1_000_000_000
 self.baseData = buffer.data().base64EncodedString()
 if isFinal {
 self.stopRecording()
 }
 }
 if engine.isRunning { return }
 try engine.start()
 }

i believe there should be something that i need to do in that install tap closure but not sure how.

asked Jan 15, 2025 at 9:30

1 Answer 1

-1

To stop the recording automatically after a specified period of silence (e.g., 5 seconds) using AVAudioEngine, you need to monitor the audio buffer’s amplitude level and detect if the audio input level stays below a certain threshold (silence threshold) for the specified duration.

func startRecording() throws {
 guard let engine = self.audioEngine, let mic = mic else { return }
 let micFormat = mic.inputFormat(forBus: 0)
 let silenceThreshold: Float = 0.01 // Adjust based on what you consider silence
 let silenceTimeout: TimeInterval = 5 // 5 seconds of silence to stop recording
 var silenceStartTime: TimeInterval? // Tracks when silence started
 self.state = .recording
 mic.installTap(onBus: 0, bufferSize: 4096, format: micFormat) { [weak self] (buffer, _) in
 guard let self = self else { return }
 // Analyze the audio buffer
 let channelData = buffer.floatChannelData?[0]
 let frameLength = Int(buffer.frameLength)
 // Compute the RMS (Root Mean Square) to detect audio level
 let rms = channelData?.prefix(frameLength).reduce(0, { 0ドル + 1ドル * 1ドル }).squareRoot() ?? 0
 // Check if the audio level is below the silence threshold
 if rms < silenceThreshold {
 // Start counting silence duration
 if silenceStartTime == nil {
 silenceStartTime = Date().timeIntervalSince1970
 } else if let startTime = silenceStartTime,
 Date().timeIntervalSince1970 - startTime > silenceTimeout {
 // Stop recording if silence duration exceeds timeout
 DispatchQueue.main.async {
 self.stopRecording()
 }
 }
 } else {
 // Reset silence start time if audio is detected
 silenceStartTime = nil
 }
 }
 if !engine.isRunning {
 try engine.start()
 }
}
func stopRecording() {
 guard let engine = self.audioEngine else { return }
 if engine.isRunning {
 engine.stop()
 mic?.removeTap(onBus: 0)
 }
 self.state = .stopped
 print("Recording stopped due to silence.")
}
answered Jan 15, 2025 at 9:42
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.