GitHunt
BI

bizz84/speech_to_text_merged_threads

Example voice-activated timer app

This example app highlights performance issues with the speech_to_text package when using merged platform and UI threads (Flutter 3.27 and above).

This example is for iOS only (Android wasn't tested but might have the same issues).

Running the app

Run the app on a real iOS device in profile or release mode.

After accepting the microphone and speech recognition permissions, use the voice-activated commands:

  • Say "start" to start the timer
  • Say "stop" to stop the timer
  • Say "reset" to reset the timer
  • Say "time" to speak the current time via TTS

Performance issues

The tests below were performed on an iPhone XR running iOS 17.6.1.

  • Calls to _speech.listen take ~0.5 seconds on average
  • Calls to _speech.stop take ~0.2 seconds on average

On Flutter 3.32.1 and master (3.33.0-1.0.pre.417), both calls cause several dropped frames (this can be observed in the StopwatchDisplay widget which fails to update the display at 60Hz), regardless of whether FLTEnableMergedPlatformUIThread is set to true or false in the Info.plist.

On Flutter 3.24.5, the calls take the same amount of time but do not cause dropped frames (separate threads).

iOS Setup

The app uses microphone and speech recognition, so it is configured as follows.

ios/Runner/Info.plist:

	<key>NSMicrophoneUsageDescription</key>
	<string>This app needs microphone access to recognize voice commands like "start" and "stop" for hands-free timer control during exercise.</string>
	<key>NSSpeechRecognitionUsageDescription</key>
	<string>This app needs speech recognition access to recognize voice commands like "start" and "stop" for hands-free timer control during exercise.</string>
	<key>FLTEnableMergedPlatformUIThread</key>
	<false/>	

ios/Podfile:

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)

    # https://github.com/Baseflow/flutter-permission-handler/issues/1391#issuecomment-2392231125
    target.build_configurations.each do |config|
      # You can remove unused permissions here
      # for more information: https://github.com/Baseflow/flutter-permission-handler/blob/main/permission_handler_apple/ios/Classes/PermissionHandlerEnums.h
      # e.g. when you don't need camera permission, just add 'PERMISSION_CAMERA=0'
      config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
        '$(inherited)',
        ## dart: PermissionGroup.microphone
        'PERMISSION_MICROPHONE=1',

        ## dart: PermissionGroup.speech
        'PERMISSION_SPEECH_RECOGNIZER=1',
      ]
    end    
  end
end

Languages

Dart86.4%Ruby10.2%Swift3.3%Objective-C0.2%

Contributors

Created June 9, 2025
Updated March 15, 2026
bizz84/speech_to_text_merged_threads | GitHunt