FDSoundActivatedRecorder - Start recording when the user speaks

Overview

FDSoundActivatedRecorder

CI Status Version License Platform Carthage compatible Readme Score

Start recording when the user speaks. All you have to do is tell us when to start listening. Then we wait for an audible noise and start recording. This is mostly useful for user speech input and the "Start talking now" prompt.

🍕 Virtual tip jar: https://amazon.com/hz/wishlist/ls/EE78A23EEGQB

Features

  • You can start recording when sound is detected, or immediately
  • Sound stops recording when the user is done talking
  • Works with ARC and iOS 5+

Installation

Add this to your project using Swift Package Manager. In Xcode that is simply: File > Swift Packages > Add Package Dependency... and you're done. Alternative installation options are shown below for legacy projects.

CocoaPods

If you are already using CocoaPods, just add 'FDSoundActivatedRecorder' to your Podfile then run pod install.

Carthage

If you are already using Carthage, just add to your Cartfile:

0.1 ">
github "fulldecent/FDSoundActivatedRecorder" ~> 0.1

Then run carthage update to build the framework and drag the built FDSoundActivatedRecorderframework into your Xcode project.

Usage

First, install by adding pod 'FDSoundActivatedRecorder', '~> 1.0.0' to your Podfile.

Import the project with:

import FDSoundActivatedRecorder

Then begin listening with:

self.recorder = FDSoundActivatedRecorder()
self.recorder.delegate = self
self.recorder.startListening()

A full implementation example is provided in this project.

If your app is in the app store, I would much appreciate if you could add your app to https://www.cocoacontrols.com/controls/fdsoundactivatedrecorder under "Apps using this control" and "I Use This Control".

Regular Recorder

If you want to use it as a regular recorder, without the ability to of trimming the audio.

  1. Begin listening:
self.recorder.startListening()
  1. Begin recording:
self.recorder.startRecording()
  1. Finally, you can stop recording using the following method:
self.recorder.stopAndSaveRecording()

Full API

The full API, from FDSoundActivatedRecorder.swift is copied below:

@objc protocol FDSoundActivatedRecorderDelegate {
    /// A recording was triggered or manually started
    func soundActivatedRecorderDidStartRecording(recorder: FDSoundActivatedRecorder)

    /// No recording has started or been completed after listening for `TOTAL_TIMEOUT_SECONDS`
    func soundActivatedRecorderDidTimeOut(recorder: FDSoundActivatedRecorder)

    /// The recording and/or listening ended and no recording was captured
    func soundActivatedRecorderDidAbort(recorder: FDSoundActivatedRecorder)

    /// A recording was successfully captured
    func soundActivatedRecorderDidFinishRecording(recorder: FDSoundActivatedRecorder, andSaved file: NSURL)
}

class FDSoundActivatedRecorder : NSObject {
    /// A log-scale reading between 0.0 (silent) and 1.0 (loud), nil if not recording
    dynamic var microphoneLevel: Double

    /// Receiver for status updates
    weak var delegate: FDSoundActivatedRecorderDelegate?

    /// Listen and start recording when triggered
    func startListening()

    /// Go back in time and start recording `RISE_TRIGGER_INTERVALS` ago
    func startRecording()

    /// End the recording and send any processed & saved file to `delegate`
    func stopAndSaveRecording()

    /// End any recording or listening and discard any recorded files
    func abort()

    /// This is a PRIVATE method but it must be public because a selector is used in NSTimer (Swift bug)
    func interval()
}

Technical discussion

This library is tuned for human speech detection using Apple retail iOS devices in a quiet or noisy environement. You are welcome to tune the audio detection constants of this program for any special needs you may have. Following is a technical description of how the algorithm works from FDSoundActivatedRecorder.swift.

V               Recording
O             /-----------\
L            /             \Fall
U           /Rise           \
M          /                 \
E  --------                   --------
   Listening                  Done
  • We listen and save audio levels every INTERVAL
  • When several levels exceed the recent moving average by a threshold, we record
  • (The exceeding levels are not included in the moving average)
  • When several levels deceed the recent moving average by a threshold, we stop recording
  • (The deceeding levels are not included in the moving average)

Sponsorship

[ YOUR LOGO HERE ]

Please contact [email protected] to discuss adding your company logo above and supporting this project.

Comments
  • iPhone 5S woes

    iPhone 5S woes

    Sync'd repo. Built and loaded on to iPhone 5S using iOS 7.1.1. Hit "Start" screen briefly flashes green and then immediately stops.

    Verified app has microphone permissions.

    Works fine in the simulator.

    opened by DreamTimerZ 10
  • Expose parameteres with default values

    Expose parameteres with default values

    It might be useful to expose the parameters currently defined as private (e.g. TOTAL_TIMEOUT_SECONDS) for configuring the recorder according to the app's needs.

    opened by leolobato 7
  • Bug when listening && timeout

    Bug when listening && timeout

    Hi.

    You have bug in your code. If status of recorder is still in "listening" and timeouts -> you never call abort on a delegate.

    I've added this to fix this:

    Line ~220 (function abort()):

    if status == .Recording || status == .Listening {

    opened by sabiland 6
  • Recording stops after 1 second, even if there is still voice !

    Recording stops after 1 second, even if there is still voice !

    Hello

    Recording stops after 1 second, even if there is still voice!

    2016-03-18 00:27:20.467 FDSoundActivatedRecorder[28121:2689565] Listening avg nan current -69.42 Intervals 0 Triggers 0 2016-03-18 00:27:20.518 FDSoundActivatedRecorder[28121:2689565] Listening avg -69.42 current -36.99 Intervals 1 Triggers 0 2016-03-18 00:27:20.567 FDSoundActivatedRecorder[28121:2689565] Listening avg -53.20 current -38.99 Intervals 2 Triggers 0 2016-03-18 00:27:20.618 FDSoundActivatedRecorder[28121:2689565] Listening avg -53.20 current -41.68 Intervals 2 Triggers 1 2016-03-18 00:27:20.668 FDSoundActivatedRecorder[28121:2689565] Listening avg -49.36 current -43.84 Intervals 3 Triggers 1 2016-03-18 00:27:20.718 FDSoundActivatedRecorder[28121:2689565] Listening avg -47.98 current -45.96 Intervals 4 Triggers 1 2016-03-18 00:27:20.768 FDSoundActivatedRecorder[28121:2689565] Listening avg -47.58 current -48.55 Intervals 5 Triggers 1 2016-03-18 00:27:20.817 FDSoundActivatedRecorder[28121:2689565] Listening avg -47.74 current -50.52 Intervals 6 Triggers 1 2016-03-18 00:27:20.868 FDSoundActivatedRecorder[28121:2689565] Listening avg -48.14 current -28.76 Intervals 7 Triggers 1 2016-03-18 00:27:20.918 FDSoundActivatedRecorder[28121:2689565] Recording avg nan current -17.57 Intervals 0 Triggers 0 2016-03-18 00:27:20.968 FDSoundActivatedRecorder[28121:2689565] Recording avg -17.57 current -0.33 Intervals 1 Triggers 0 2016-03-18 00:27:21.018 FDSoundActivatedRecorder[28121:2689565] Recording avg -8.95 current 0.23 Intervals 2 Triggers 0 2016-03-18 00:27:21.067 FDSoundActivatedRecorder[28121:2689565] Recording avg -5.89 current 2.47 Intervals 3 Triggers 0 2016-03-18 00:27:21.118 FDSoundActivatedRecorder[28121:2689565] Recording avg -3.80 current 2.35 Intervals 4 Triggers 0 2016-03-18 00:27:21.168 FDSoundActivatedRecorder[28121:2689565] Recording avg -2.57 current 0.99 Intervals 5 Triggers 0 2016-03-18 00:27:21.217 FDSoundActivatedRecorder[28121:2689565] Recording avg -1.98 current -0.81 Intervals 6 Triggers 0 2016-03-18 00:27:21.268 FDSoundActivatedRecorder[28121:2689565] Recording avg -1.81 current -1.12 Intervals 7 Triggers 0 2016-03-18 00:27:21.317 FDSoundActivatedRecorder[28121:2689565] Recording avg -1.72 current 1.50 Intervals 8 Triggers 0 2016-03-18 00:27:21.368 FDSoundActivatedRecorder[28121:2689565] Recording avg -1.36 current 1.87 Intervals 9 Triggers 0 2016-03-18 00:27:21.418 FDSoundActivatedRecorder[28121:2689565] Recording avg -1.04 current 2.44 Intervals 10 Triggers 0 2016-03-18 00:27:21.467 FDSoundActivatedRecorder[28121:2689565] Recording avg -0.73 current 1.36 Intervals 11 Triggers 0 2016-03-18 00:27:21.518 FDSoundActivatedRecorder[28121:2689565] Recording avg -0.55 current -0.67 Intervals 12 Triggers 0 2016-03-18 00:27:21.568 FDSoundActivatedRecorder[28121:2689565] Recording avg -0.55 current -3.07 Intervals 12 Triggers 1 2016-03-18 00:27:21.570 FDSoundActivatedRecorder[28121:2689565] FDSoundActivatedRecorder saving cleaned file to file:///Users/ElSifi/Library/Developer/CoreSimulator/Devices/CF286E04-B175-436A-8250-1FB38F7EFAAC/data/Containers/Data/Application/8AB7A910-0061-4ADE-9571-C84A91AC8A0A/tmp/recordingConverted392A3DC9-F204-43D6-B912-F2CBC92F5DA9.caf 2016-03-18 00:27:21.573 FDSoundActivatedRecorder[28121:2689565] FDSoundActivatedRecorder audio export started 2016-03-18 00:27:21.590 FDSoundActivatedRecorder[28121:2692389] FDSoundActivatedRecorder audio export succeeded 2016-03-18 00:27:23.322 FDSoundActivatedRecorder[28121:2689565] FDSoundActivatedRecorder saving cleaned file to file:///Users/ElSifi/Library/Developer/CoreSimulator/Devices/CF286E04-B175-436A-8250-1FB38F7EFAAC/data/Containers/Data/Application/8AB7A910-0061-4ADE-9571-C84A91AC8A0A/tmp/recordingConverted9ADA5122-4ECB-49B9-81E4-AF63ED3ACC92.caf 2016-03-18 00:27:23.324 FDSoundActivatedRecorder[28121:2689565] FDSoundActivatedRecorder audio export started 2016-03-18 00:27:23.343 FDSoundActivatedRecorder[28121:2692388] FDSoundActivatedRecorder audio export succeeded

    opened by ElSifi 5
  • Regular recording without trimming

    Regular recording without trimming

    Hello, First of all, thanks for creating this amazing repo. It really helped me a lot!

    In my app use case, I want to provide a way for users to record regularly just like any other audio recorder without trimming the audio, starting when the user starts speaking, or anything.

    I tried to use the startRecording method however when I tap on my stop recording button, the exportSession inside the stopAndSaveRecording fails with an export status of 4 which means it failed. Therefore, it doesn't call the soundActivatedRecorderDidFinishRecording delegate method.

    What I'm doing wrong, and how can I fix it?

    Thanks!

    opened by HassanElDesouky 3
  • update to swift 4

    update to swift 4

    In the FDSoundActivatedRecorder.swift must change the following

    @objc dynamic open var microphoneLevel: Double = 0.0 // line 135 in FDSoundActivatedRecorder.swift intervalTimer = Timer.scheduledTimer(timeInterval: intervalSeconds, target: self, selector: #selector(FDSoundActivatedRecorder.interval), userInfo: nil, repeats: true) // line 149 in FDSoundActivatedRecorder.swift let tracks = avAsset.tracks(withMediaType: AVMediaType.audio) // line 193 in FDSoundActivatedRecorder.swift exportSession.outputFileType = AVFileType.m4a // line 204 in FDSoundActivatedRecorder.swift

    opened by aserdah 3
  • "Regular Recorder" functions are not working in the example

    Hi there,

    Thank you for this easy to use package.

    Although "listening" & "playback" functions works perfect, I was not able get "Regular Recorder" functions working in the example project.

    I also tried as stated in https://github.com/fulldecent/FDSoundActivatedRecorder/issues/31 but all it changed was -> started recording without trigger & stopped recording with same behaviour as listening.

    So, I looked at the source code and realised that every timer interval there is a check which stops recording. if let triggerLevel = triggerLevel, currentLevel <= triggerLevel { I think that is the line of code that needs an update, there can be a check here for regular recording use cases.


    I introduced regularRecording to see a working example; to start regular recorder ->

            recorder.regularRecording = true
            recorder.startListening()
            recorder.startRecording()
    

    to stop recorder ->

            recorder.stopAndSaveRecording()
            recorder.regularRecording = false
    

    initialize ->

    class FDSoundActivatedRecorderMock: FDSoundActivatedRecorder {
        var intervalCallback: (Float)->() = {_ in}
        var regularRecording = false
        override func interval(currentLevel: Float) {
            self.intervalCallback(currentLevel)
            if regularRecording == false {
                super.interval(currentLevel: currentLevel)
            }
        }
        override init() {
            super.init()
        }
    }
    

    Best Regards, Engin

    opened by engblnk 2
  • Expose and adjust silence level threshold

    Expose and adjust silence level threshold

    Sorry for not including this on the last release. :)

    I see microphoneLevel actually discard values below -85dB, which would be considered silence.

    In my experience using the library, I've noticed a fairly silent room (windows closed, empty house) meters around -44dB without anyone speaking, and presenting this as a visual level cue to the user is helpful to let them know if the library will or not easily detect speech (and a silent ambient also contributes to a better speech recognition, which is why I am using this library).

    So if they see the visual microphone level "empty", they will understand they are at a good environment for speech recognition. If they see the level moving (or even half-full), they'll understand they're at a noisy ambient and will speak closer to the microphone (or switch to a headset).

    I'm creating a new pull request with two separate commits:

    • Expose a microphoneLevelThreshold property and;
    • Changing its default value from -85 to -44db

    Feel free to discard the default value change if you think the previous was better.

    opened by leolobato 2
  • Use adaptive algorithm for determining if a user speaks

    Use adaptive algorithm for determining if a user speaks

    This is somewhat related to issue https://github.com/fulldecent/FDSoundActivatedRecorder/issues/20.

    Idea:

    1. save the last x microphone levels (e.g. for the last 30 seconds)
    2. identify spikes: these would indicate that a user speaks
    3. substract spikes from other saved levels in order identify valleys: these would indicate silence
    4. use average of valleys as the threshold value for speaking
    5. if the current microphone level is greater than the moving average, user is probably speaking

    The advantage of such an algorithm is obvious: even if the surrounding circumstances change (e.g. the user leaves a building and is exposed to traffic noise), the recognition accuracy would still be high.

    opened by MHX792 1
  • Continous Listening without Recording?

    Continous Listening without Recording?

    I just want to get a notification when a user starts speaking, without the need of recording anything.

    For this, I have set the timeoutSeconds to zero for indefinite listening.

           self.recorder.timeoutSeconds = 0
           self.recorder.startListening()
    

    Is anything saved in the background by using startListeening()? If yes, this would prevent indefinite listening because of storage limitations.

    opened by MHX792 1
  • Adopt layout from https://github.com/fulldecent/swift5-module-template

    Adopt layout from https://github.com/fulldecent/swift5-module-template

    A modern project layout for Swift modules is defined at https://github.com/fulldecent/swift5-module-template

    Work plan

    • [ ] Study best practices at link above
    • [ ] Apply the "Recipe" from the Swift 5 Module Template to this project
    • [ ] Ensure that PR does not change the current development team

    Follow-on work

    • [ ] Make a minor version feature release with this updated project
    opened by fulldecent 1
Releases(3.2.0)
Owner
William Entriken
EN/中文 [email protected]
William Entriken
AudiosPlugin is a Godot iOS Audio Plugin that resolves the audio recording issue in iOS for Godot Engine.

This plugin solves the Godot game engine audio recording and playback issue in iOS devices. Please open the Audios Plugin XCode Project and compile the project. You can also use the libaudios_plugin.a binary in your project.

null 3 Dec 22, 2022
🗣Voice overlay helps you turn your user's voice into text, providing a polished UX while handling for you the necessary permissions

Voice overlay helps you turn your user's voice into text, providing a polished UX while handling for you the necessary permissions. It uses i

Algolia 490 Dec 19, 2022
A drop-in universal library allows to record audio within the app with a nice User Interface.

IQAudioRecorderController IQAudioRecorderController is a drop-in universal library allows to record and crop audio within the app with a nice User Int

Mohd Iftekhar Qurashi 637 Nov 17, 2022
Recording Indicator Utility lets you turn off the orange microphone recording indicator light for live events and screencasts.

Recording Indicator Utility Recording Indicator Utility lets you turn off the orange microphone recording indicator light, making it ideal for profess

Tyshawn Cormier 121 Jan 1, 2023
Don't start from scratch, start from Here! This is a starter project for iOS projects. It contains all the basic configurations and common libraries for your project.

Starter-iOS Don't start from scratch, start from Here! This is a starter project for iOS projects. It contains all the basic configurations and common

Shaban Kamel 6 May 24, 2022
An App that gives a nice interface where the user can type in their start location and destination

SixtCarSummoner What it does We developed an App that gives a nice interface where the user can type in their start location and destination. The user

Dominik Schiwietz 1 Nov 21, 2021
Location, motion, and activity recording framework for iOS

LocoKit A Machine Learning based location recording and activity detection framework for iOS. Location and Motion Recording Combined, simplified Core

Matt Greenfield 1.5k Jan 2, 2023
In-app screen recording using ReplayKit in iOS. Written in Swift 5 on Xcode 12.3

In-App-ScreenRecording-iOS In-app screen recording using ReplayKit in iOS. Written in Swift 5 on Xcode 12.3 Features: Recording application screen onl

Ahmed Abdelkarim 4 Dec 23, 2022
RadialMenu is a custom control for providing a touch context menu (like iMessage recording in iOS 8) built with Swift & POP

RadialMenu Looking for help? For $150/hr I'll help with your RadialMenu problems including integrating it into your project. Email [email protected] t

Brad Jasper 297 Nov 27, 2022
OutRun is an iOS app for recording and viewing your outdoor workouts

OutRun is an iOS app for recording and viewing your outdoor workouts. Despite the name it supports not just running, but also walking, hiking, cycling and skating.

Tim Fraedrich 195 Dec 28, 2022
AudiosPlugin is a Godot iOS Audio Plugin that resolves the audio recording issue in iOS for Godot Engine.

This plugin solves the Godot game engine audio recording and playback issue in iOS devices. Please open the Audios Plugin XCode Project and compile the project. You can also use the libaudios_plugin.a binary in your project.

null 3 Dec 22, 2022
RadialMenu is a custom control for providing a touch context menu (like iMessage recording in iOS 8) built with Swift & POP

RadialMenu Looking for help? For $150/hr I'll help with your RadialMenu problems including integrating it into your project. Email [email protected] t

Brad Jasper 297 Nov 27, 2022
Start your next Open-Source Swift Framework 📦

SwiftKit enables you to easily generate a cross platform Swift Framework from your command line. It is the best way to start your next Open-Source Swi

Sven Tiigi 821 Dec 28, 2022
A better way to present a SFSafariViewController or start a ASWebAuthenticationSession in SwiftUI.

BetterSafariView A better way to present a SFSafariViewController or start a ASWebAuthenticationSession in SwiftUI. Contents Motivation Requirements U

Dongkyu Kim 392 Dec 31, 2022
Custom Time Picker ViewController with Selection of start and end times in Swift 🔶

LFTimePicker Custom Time Picker ViewController with Selection of start and end times in Swift ?? . Based on Adey Salyard's design @ Dribbble One to tw

Awesome Labs 65 Nov 11, 2022
This is a Swift package with support for macOS that allows to start Java Jar's with the default or a custom JVM.

Jar.swift jar runner for macos Jar.swift is created and maintaned with ❥ by Sascha Muellner. What? This is a Swift package with support for macOS that

Swift Package Repository 1 Nov 11, 2021
A better way to present a SFSafariViewController or start a ASWebAuthenticationSession in SwiftUI

A better way to present a SFSafariViewController or start a ASWebAuthenticationSession in SwiftUI.

Billy 4 Sep 26, 2022
You can easily start up a little breaking game by one line.

JDBreaksLoading Introduction JDBreaksLoading Based on simple UIView and SpriteKit. You can easily start up a little breaking game by one line. By the

郭介騵 155 Nov 2, 2022
Swift extension which adds start, animating and completion closures for CAAnimation objects. Aka, CAAnimation + Closure / Block

Swift-CAAnimation-Closure Swift extension which adds start, animating and completion closures for CAAnimation objects. Aka, CAAnimation + Closure or C

HongHao Zhang 112 Jun 17, 2022
Allows a swipe on any part of the screen to start an interruptible pop animation to the previous view

Lazy Pop SwiftUI Swiping on any part of the screen starts an interruptible pop animation to the previous view. Forked from https://github.com/rishi420

Joe Hinkle 150 Dec 18, 2022