{"id":1425,"url":"https://github.com/algolia/voice-overlay-ios","last_synced_at":"2025-06-19T15:42:25.612Z","repository":{"id":41811269,"uuid":"138575203","full_name":"algolia/voice-overlay-ios","owner":"algolia","description":"🗣 An overlay that  gets your user’s voice permission and input as text in a customizable UI","archived":false,"fork":false,"pushed_at":"2022-10-06T20:56:11.000Z","size":23125,"stargazers_count":551,"open_issues_count":13,"forks_count":61,"subscribers_count":53,"default_branch":"master","last_synced_at":"2025-05-29T09:59:34.962Z","etag":null,"topics":["chatbots","conversation","conversational-bots","conversational-interface","conversational-ui","input","instant-search","instantsearch","ios","objective-c","overlay","permissions","search","speech-recognition","speech-to-text","swift","voice","voice-assistant","voice-recognition","voicetext"],"latest_commit_sha":null,"homepage":"https://alg.li/voice","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/algolia.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-06-25T09:48:14.000Z","updated_at":"2025-05-15T18:33:55.000Z","dependencies_parsed_at":"2022-08-20T21:20:20.889Z","dependency_job_id":null,"html_url":"https://github.com/algolia/voice-overlay-ios","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/algolia/voice-overlay-ios","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/algolia%2Fvoice-overlay-ios","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/algolia%2Fvoice-overlay-ios/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/algolia%2Fvoice-overlay-ios/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/algolia%2Fvoice-overlay-ios/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/algolia","download_url":"https://codeload.github.com/algolia/voice-overlay-ios/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/algolia%2Fvoice-overlay-ios/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260781387,"owners_count":23062231,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chatbots","conversation","conversational-bots","conversational-interface","conversational-ui","input","instant-search","instantsearch","ios","objective-c","overlay","permissions","search","speech-recognition","speech-to-text","swift","voice","voice-assistant","voice-recognition","voicetext"],"created_at":"2024-01-05T20:15:46.166Z","updated_at":"2025-06-19T15:42:20.585Z","avatar_url":"https://github.com/algolia.png","language":"Swift","funding_links":[],"categories":["Media","Libs","Media and Graphics","Audio [🔝](#readme)","Swift"],"sub_categories":["Audio"],"readme":"![Voice Overlay for iOS](./Resources/banner_voice_overlay.png)\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://img.shields.io/badge/platform-iOS-blue.svg?style=flat\" alt=\"Platform iOS\" /\u003e\n\u003ca href=\"https://developer.apple.com/swift\"\u003e\u003cimg src=\"https://img.shields.io/badge/swift4-compatible-4BC51D.svg?style=flat\" alt=\"Swift 4 compatible\" /\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/Carthage/Carthage\"\u003e\u003cimg src=\"https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat\" alt=\"Carthage compatible\" /\u003e\u003c/a\u003e\n\u003ca href=\"https://cocoapods.org/pods/InstantSearchVoiceOverlay\"\u003e\u003cimg src=\"https://img.shields.io/cocoapods/v/InstantSearchVoiceOverlay.svg\" alt=\"CocoaPods compatible\" /\u003e\u003c/a\u003e\n\u003ca href=\"LICENSE.md\"\u003e\u003cimg src=\"http://img.shields.io/badge/license-MIT-blue.svg?style=flat\" alt=\"License: MIT\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n# Overview\n\n**Voice overlay** helps you turn your user's **voice** into **text**, providing a **polished UX** while handling for you the **necessary permissions**.\n\nIt uses internally the native `SFSpeechRecognizer` in order to perform the speech to text conversion.\n\n\u003cp float=\"left\"\u003e\n  \u003cimg src=\"./Resources/permission.png\" width=\"200\" /\u003e\n  \u0026nbsp;\n  \u003cimg src=\"./Resources/listeninginitial.png\" width=\"200\" /\u003e\n  \u0026nbsp;\n  \u003cimg src=\"./Resources/ripple.gif\" width=\"200\" /\u003e\n  \u0026nbsp;\n  \u003cimg src=\"./Resources/nopermission.png\" width=\"200\" /\u003e\n  \u0026nbsp;\n\u003c/p\u003e\n\n# Demo\n\nYou can clone and run the Demo project by doing `pod install` and then running the project\n\n\u003c!-- \u003cimg src=\"./Resources/voiceoverlay_speech_happy_path.gif\" width=\"205\"\u003e --\u003e\n\n\u003cimg src=\"./Resources/demo.gif\" width=\"250\"\u003e\n\n# Installation\n\n### Swift Package Manager\n\nThe Swift Package Manager is a tool for managing the distribution of Swift code. It’s integrated with the Swift build system to automate the process of downloading, compiling, and linking dependencies. \n\nTo use SwiftPM, you should use Xcode 11+ to open your project. Click `File` -\u003e `Swift Packages` -\u003e `Add Package Dependency`, enter [InstantSearch VoiceOverlay repo's URL](https://github.com/algolia/voice-overlay-ios).\n\nIf you're a framework author and use VoiceOverlay as a dependency, update your `Package.swift` file:\n\n```swift\nlet package = Package(\n    // 1.1.0 ..\u003c 2.0.0\n    dependencies: [\n        .package(url: \"https://github.com/algolia/voice-overlay-ios\", from: \"1.1.0\")\n    ],\n    // ...\n)\n```\n\n#### CocoaPods\n\n`InstantSearchVoiceOverlay` is available through [CocoaPods](http://cocoapods.org). To install\nit, add the following line to your Podfile:\n\n```ruby\npod 'InstantSearchVoiceOverlay', '~\u003e 1.1.0'\n```\n\n### Carthage\n\n[Carthage](https://github.com/Carthage/Carthage) is a simple, decentralized dependency manager for Cocoa.\n\nTo install InstantSearchVoiceOverlay, add the following line to your Cartfile:\n\n```ruby\ngithub \"algolia/voice-overlay-ios\" ~\u003e 1.1.0\n```\n\n# Usage\n\n1. In `Info.plist`, add these 2 string properties along with the description\n\n- `Privacy - Microphone Usage Description` with a description like: `Need the mic for audio to text`\n- `Privacy - Speech Recognition Usage Description` some description like: `Need the speech recognition capabilities for searching tags`\n\n\u003cimg src=\"./Resources/infoplist.png\" width=\"700\"\u003e\n\n2. Start the Voice Overlay and listen to the text output:\n\n```swift\nimport InstantSearchVoiceOverlay\n\nclass ViewController: UIViewController {\n    \n    let voiceOverlayController = VoiceOverlayController()\n    \n    @objc func voiceButtonTapped() {\n        \n        voiceOverlayController.start(on: self, textHandler: { (text, final) in\n            print(\"voice output: \\(String(describing: text))\")\n            print(\"voice output: is it final? \\(String(describing: final))\")\n        }, errorHandler: { (error) in\n            print(\"voice output: error \\(String(describing: error))\")\n        })\n    }\n```\n\n## Customization\n\nYou can customize your voice overlay by modifying the `settings` property of the voiceOverlayController:\n\n```swift\n/// Specifies whether the overlay directly starts recording (true), \n/// or if it requires the user to click the mic (false). Defaults to true.\nvoiceOverlayController.settings.autoStart = true\n\n/// Specifies whether the overlay stops recording after the user stops talking for `autoStopTimeout`\n/// seconds (true), or if it requires the user to click the mic (false). Defaults to true.\nvoiceOverlayController.settings.autoStop = true\n\n/// When autoStop is set to true, autoStopTimeout determines the amount of\n/// silence time of the user that causes the recording to stop. Defaults to 2.\nvoiceOverlayController.settings.autoStopTimeout = 2\n\n/// The layout and style of all screens of the voice overlay.\nvoiceOverlayController.settings.layout.\u003csomeScreen\u003e.\u003csomeConstant\u003e\n\n// Use XCode autocomplete to see all possible screens and constants that are customisable.\n// Examples:\n\n/// The voice suggestions that appear in bullet points\nvoiceOverlayController.settings.layout.inputScreen.subtitleBulletList = [\"Suggestion1\", \"Sug2\"]\n/// Change the title of the input screen when the recording is ongoing.\nvoiceOverlayController.settings.layout.inputScreen.titleListening = \"my custom title\"\n/// Change the background color of the permission screen.\nvoiceOverlayController.settings.layout.permissionScreen.backgroundColor = UIColor.red\n/// And many more...\n```\n\n### Changing Locale or SpeechController\n\nYou can change locale or SpeechController when initializing your voiceOverlayController like so:\n\n``` swift\nlazy var voiceOverlayController: VoiceOverlayController = {\n  let recordableHandler = {\n    return SpeechController(locale: Locale(identifier: \"en_US\"))\n  }\n  return VoiceOverlayController(speechControllerHandler: recordableHandler)\n}()\n```\n\nYou can create your own custom SpeechController class by implementing the `Recordable` protocol.\n\nNote that in Swift 4, you can use `Locale.current.languageCode` to get current locale.\n\n## Delegate\nOptionally, to listen to text and error events, you can conform to the method of the `VoiceOverlayDelegate` protocol.\n\n```swift\n// Second way to listen to recording through delegate\nfunc recording(text: String?, final: Bool?, error: Error?) {\n    if let error = error {\n        print(\"delegate: error \\(error)\")\n    }\n    \n    if error == nil {\n        print(\"delegate: text \\(text)\")\n    }\n}\n```\n\n## How it handles when Permissions are missing\n\nWhen there are missing permissions, the voice overlay will guide the user to the correct section of the settings app.\n\n\u003cimg src=\"./Resources/nopermission.gif\" width=\"210\"\u003e\n\n## Result Screen (Beta)\n\n\u003cimg src=\"./Resources/voiceoverlay_result_screen.gif\" width=\"200\"\u003e\n\nThe result screen appears when `showResultScreen` is set to true.\n\n```swift\n/// Whether or not to show a result screen after the recording is finished.\nvoiceOverlayController.settings.showResultScreen = true\n\n/// Timeout for showing the result screen in case no resultScreenText is provided on time.\nvoiceOverlayController.settings.showResultScreenTimeout = 2\n\n/// Time for showing the result screen with the provided resultScreenText.\nvoiceOverlayController.settings.showResultScreenTime = 4\n\n/// The processed result screen text that should be appear in the result screen.\nvoiceOverlayController.settings.resultScreenText = NSAttributedString(string: myString, attributes: myAttributes)\n```\nThe widget provides a `resultScreenHandler` for when the result screen is dismissed (provided the \"Start again\" button is not clicked). The handler provides the text that has been set in `resultScreenText` beforehand.\n\n```swift\nvoiceOverlayController.start(on: self, textHandler: { (text, final) in\n    print(\"getting \\(String(describing: text))\")\n    print(\"is it final? \\(String(describing: final))\")\n\n    if final {\n        // Process the result to post in the result screen.\n        // The timer here simulates a network processing call that took 1.5 seconds.\n        Timer.scheduledTimer(withTimeInterval: 1.5, repeats: false, block: { (_) in\n            let myString = text\n            let myAttribute = [ NSAttributedString.Key.foregroundColor: UIColor.red ]\n            let myAttrString = NSAttributedString(string: myString, attributes: myAttribute)\n\n            self.voiceOverlayController.settings.resultScreenText = myAttrString\n        })\n    }\n}, errorHandler: { (error) in\n    print(\"error \\(String(describing: error))\")\n}, resultScreenHandler: { (text) in\n    print(\"Result Screen: \\(text)\")\n})\n```\n\n## Getting Help\n\n- **Need help**? Ask a question to the [Algolia Community](https://discourse.algolia.com/) or on [Stack Overflow](http://stackoverflow.com/questions/tagged/algolia).\n- **Found a bug?** You can open a [GitHub issue](https://github.com/algolia/instantsearch-ios-insights).\n- **Questions about Algolia?** You can search our [FAQ in our website](https://www.algolia.com/doc/faq/).\n\n\n## Getting involved\n\n* If you **want to contribute** please feel free to **submit pull requests**.\n* If you **have a feature request** please **open an issue**.\n* If you use **InstantSearch** in your app, we would love to hear about it! Drop us a line on [discourse](https://discourse.algolia.com/) or [twitter](https://twitter.com/algolia).\n\n## License\n\nInstantSearchVoiceOverlay is available under the MIT license. See the [LICENSE file](./LICENSE.md) for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falgolia%2Fvoice-overlay-ios","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falgolia%2Fvoice-overlay-ios","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falgolia%2Fvoice-overlay-ios/lists"}