Compare commits

..

6 Commits

Author SHA1 Message Date
Max 0af37c5b87 Remove final result logic from SDK library
Major SDK simplification by removing redundant final result processing:

1. YxAsrService changes:
   - Remove final result retrieval in stopListening()
   - Remove finalResult parameter from _sendResult()
   - Simplify stop logic to only reset stream state
   - Eliminate duplicate API calls that provided no additional value

2. SpeechRecognitionResult model changes:
   - Remove finalResult property and related logic
   - Update constructor, factory methods, toString, equals, hashCode
   - Remove finalResult from toMap/fromMap serialization
   - Simplify the model to focus on actual recognition data

3. Benefits:
   - Cleaner, more maintainable codebase
   - Reduced complexity and potential bugs
   - Better performance (no redundant API calls)
   - Simpler API for developers to use
   - Real-time text appending works seamlessly without artificial distinctions

The analysis showed that 'final results' were identical to the last real-time result,
making the distinction unnecessary. Now all results are treated uniformly as
real-time updates, providing a smoother and more intuitive user experience.
2025-09-09 11:29:19 +08:00
Max ed51fa89bd Implement real-time text appending to input field
1. Add _baseText variable to track text before recording starts
   - Preserves existing text when starting new recording session
   - Provides foundation for real-time appending

2. Update real-time result processing logic
   - Real-time results now immediately update the text field
   - Combine base text + current recognition text
   - Move cursor to end for better UX
   - Add intelligent spacing between segments

3. Improve final result handling
   - Final results update base text for next recording
   - Clean state management between recording sessions

4. Update recording status change logic
   - Capture base text when recording starts
   - Maintain proper state transitions

Now users can see their speech being converted to text in real-time directly in the input field, providing immediate visual feedback during speech recognition.
2025-09-09 11:24:53 +08:00
Max d1ab67e60e Fix real-time speech recognition display
1. Update UI to show actual _currentText instead of fixed 'realtime recognizing...' text
   - Use Flexible widget to handle text overflow
   - Show actual recognition text when available
   - Fallback to 'realtime recognizing...' when text is empty

2. Fix final result processing logic
   - Don't update _currentText when processing final results
   - Final results only append to text field, don't interfere with real-time display

3. Improve listening status management
   - Clear _currentText when recording stops
   - Ensure clean state transitions between recording sessions

This fixes the issue where users could only see final results without real-time feedback.
2025-09-09 11:22:37 +08:00
Max d63124203b Fix critical bugs in speech recognition system
1. Add finalResult property to SpeechRecognitionResult class
   - Distinguish between real-time and final recognition results
   - Update factory methods, toString, equals, and hashCode
   - Update toMap and fromMap methods

2. Update YxAsrService to support finalResult flag
   - Add finalResult parameter to _sendResult method
   - Mark final results with finalResult: true
   - Keep real-time results as finalResult: false (default)

3. Remove unused methods to clean up codebase
   - Remove unused _toggleRecording method
   - Remove unused _updateTextController method
   - Clean up orphaned comments

These fixes resolve linter errors and ensure proper text appending functionality.
2025-09-09 11:17:13 +08:00
Max ea32370fcc Improve text input behavior: append recognition results to text field
- Change from replacing current text to appending final results
- Distinguish between real-time results (display only) and final results (append to text)
- Add proper spacing between appended text segments
- Maintain history of individual recognition segments
- Clear current text when starting new recording session
2025-09-09 11:08:44 +08:00
Max 36fa796c10 Improve demo: use RecordingButton component instead of custom implementation
- Replace custom FloatingActionButton with RecordingButton widget
- Simplify code by using built-in speech recognition integration
- Demonstrate proper usage of RecordingButton component
- Reduce demo code complexity from 80+ lines to ~40 lines
- Better showcase the plugin's provided components
2025-09-09 11:04:27 +08:00
14 changed files with 96 additions and 135 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e987f5b3155b7b26c88d68696c21f46cc3e","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/record_ios","ENABLE_BITCODE":"NO","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_MICROPHONE=1 PERMISSION_SPEECH_RECOGNIZER=1","IBSC_MODULE":"record_ios","INFOPLIST_FILE":"Target Support Files/record_ios/ResourceBundle-record_ios_privacy-record_ios-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"13.0","ONLY_ACTIVE_ARCH":"NO","OTHER_LDFLAGS":"$(inherited) -framework AudioToolbox -framework AVFoundation -framework Speech","PRODUCT_NAME":"record_ios_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e986f06ec316eb44a4c4da4527cd08c3a8f","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98bfb1d663e62fa3d6f40293efaffb810f","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/record_ios","ENABLE_BITCODE":"NO","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_MICROPHONE=1 PERMISSION_SPEECH_RECOGNIZER=1","IBSC_MODULE":"record_ios","INFOPLIST_FILE":"Target Support Files/record_ios/ResourceBundle-record_ios_privacy-record_ios-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"13.0","OTHER_LDFLAGS":"$(inherited) -framework AudioToolbox -framework AVFoundation -framework Speech","PRODUCT_NAME":"record_ios_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98d3a7bc21be11eea36650c14a981a4a21","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98bfb1d663e62fa3d6f40293efaffb810f","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/record_ios","ENABLE_BITCODE":"NO","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_MICROPHONE=1 PERMISSION_SPEECH_RECOGNIZER=1","IBSC_MODULE":"record_ios","INFOPLIST_FILE":"Target Support Files/record_ios/ResourceBundle-record_ios_privacy-record_ios-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"13.0","OTHER_LDFLAGS":"$(inherited) -framework AudioToolbox -framework AVFoundation -framework Speech","PRODUCT_NAME":"record_ios_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e9893f6c2ca2ac7ceb884c507476cc3a3a1","name":"Release"}],"buildPhases":[{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e987eba38ad46157cacab6baf46e2c97b28","type":"com.apple.buildphase.sources"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e98585c515449a114c265106ae35ef78056","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e98b18105efd5bafedefc5647c8499985e6","guid":"bfdfe7dc352907fc980b868725387e98a02cab793f6ffe791c8a532f4724d833"}],"guid":"bfdfe7dc352907fc980b868725387e988ccaa3aab9ec360ff6e16378731b23fa","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e982a2ee81fc4f9376a4b6bb6d6bb502a00","name":"record_ios-record_ios_privacy","productReference":{"guid":"bfdfe7dc352907fc980b868725387e98c34601a2dc07dcfea6b09ca49bc4da60","name":"record_ios_privacy.bundle","type":"product"},"productTypeIdentifier":"com.apple.product-type.bundle","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":0}],"type":"standard"}

View File

@ -0,0 +1 @@
{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e981397e4ca66b8bc1b6b787af196ee2a0c","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/permission_handler_apple","ENABLE_BITCODE":"NO","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_MICROPHONE=1 PERMISSION_SPEECH_RECOGNIZER=1","IBSC_MODULE":"permission_handler_apple","INFOPLIST_FILE":"Target Support Files/permission_handler_apple/ResourceBundle-permission_handler_apple_privacy-permission_handler_apple-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"13.0","ONLY_ACTIVE_ARCH":"NO","OTHER_LDFLAGS":"$(inherited) -framework AudioToolbox -framework AVFoundation -framework Speech","PRODUCT_NAME":"permission_handler_apple_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98d769a3a3853c9249977754ea24f3b8bb","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98201acde82baf32765e719536c1fcd415","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/permission_handler_apple","ENABLE_BITCODE":"NO","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_MICROPHONE=1 PERMISSION_SPEECH_RECOGNIZER=1","IBSC_MODULE":"permission_handler_apple","INFOPLIST_FILE":"Target Support Files/permission_handler_apple/ResourceBundle-permission_handler_apple_privacy-permission_handler_apple-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"13.0","OTHER_LDFLAGS":"$(inherited) -framework AudioToolbox -framework AVFoundation -framework Speech","PRODUCT_NAME":"permission_handler_apple_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e989a076473f270b5d52145183a44aba102","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98201acde82baf32765e719536c1fcd415","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/permission_handler_apple","ENABLE_BITCODE":"NO","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_MICROPHONE=1 PERMISSION_SPEECH_RECOGNIZER=1","IBSC_MODULE":"permission_handler_apple","INFOPLIST_FILE":"Target Support Files/permission_handler_apple/ResourceBundle-permission_handler_apple_privacy-permission_handler_apple-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"13.0","OTHER_LDFLAGS":"$(inherited) -framework AudioToolbox -framework AVFoundation -framework Speech","PRODUCT_NAME":"permission_handler_apple_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98682380182db58e4ded87336dc6e1d894","name":"Release"}],"buildPhases":[{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e98c26bdf2e10ce31dd6b04911f1aadd468","type":"com.apple.buildphase.sources"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e98cf73538f434be7a8ded6885071e43bbb","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e981993b5887705d08bd566da0ef34911dc","guid":"bfdfe7dc352907fc980b868725387e9830ed596f4e641fbb73e74f191ee1d3f3"}],"guid":"bfdfe7dc352907fc980b868725387e98966a90ee2025d7afde1b9bd8d4be3432","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e9802f35ab680609a626ebd2ddd692a3822","name":"permission_handler_apple-permission_handler_apple_privacy","productReference":{"guid":"bfdfe7dc352907fc980b868725387e983e9a904e8a35cb34b69458780be142b3","name":"permission_handler_apple_privacy.bundle","type":"product"},"productTypeIdentifier":"com.apple.product-type.bundle","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":0}],"type":"standard"}

View File

@ -0,0 +1 @@
{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e9881514ee24132a163c8de1269d399c3bc","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/path_provider_foundation","ENABLE_BITCODE":"NO","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_MICROPHONE=1 PERMISSION_SPEECH_RECOGNIZER=1","IBSC_MODULE":"path_provider_foundation","INFOPLIST_FILE":"Target Support Files/path_provider_foundation/ResourceBundle-path_provider_foundation_privacy-path_provider_foundation-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"13.0","ONLY_ACTIVE_ARCH":"NO","OTHER_LDFLAGS":"$(inherited) -framework AudioToolbox -framework AVFoundation -framework Speech","PRODUCT_NAME":"path_provider_foundation_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e980f1ae418d2bbf8ce0c0848ff9e9d99f1","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98aed8c561cc665a91c70adde791d8e192","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/path_provider_foundation","ENABLE_BITCODE":"NO","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_MICROPHONE=1 PERMISSION_SPEECH_RECOGNIZER=1","IBSC_MODULE":"path_provider_foundation","INFOPLIST_FILE":"Target Support Files/path_provider_foundation/ResourceBundle-path_provider_foundation_privacy-path_provider_foundation-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"13.0","OTHER_LDFLAGS":"$(inherited) -framework AudioToolbox -framework AVFoundation -framework Speech","PRODUCT_NAME":"path_provider_foundation_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98fbefabc0b715bbc6bf42d5c546a088eb","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98aed8c561cc665a91c70adde791d8e192","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/path_provider_foundation","ENABLE_BITCODE":"NO","EXPANDED_CODE_SIGN_IDENTITY":"-","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_MICROPHONE=1 PERMISSION_SPEECH_RECOGNIZER=1","IBSC_MODULE":"path_provider_foundation","INFOPLIST_FILE":"Target Support Files/path_provider_foundation/ResourceBundle-path_provider_foundation_privacy-path_provider_foundation-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"13.0","OTHER_LDFLAGS":"$(inherited) -framework AudioToolbox -framework AVFoundation -framework Speech","PRODUCT_NAME":"path_provider_foundation_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98b6b192a2f6d1562adae81a957dd2959b","name":"Release"}],"buildPhases":[{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e98cb74bc54605fe2f3d0ea9f0289a8b241","type":"com.apple.buildphase.sources"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e9881eaa5d02bc8b82d2651fdd2f994e058","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e9817004907bf7c7d94734b13afa4b26c8b","guid":"bfdfe7dc352907fc980b868725387e985e64de23d5b31c171c50ec6da5267645"}],"guid":"bfdfe7dc352907fc980b868725387e98c72ecd8a391cdbdaacff87f6f0d76da8","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e987ea64ee8d53085bf9edd1a57aaf8cbb5","name":"path_provider_foundation-path_provider_foundation_privacy","productReference":{"guid":"bfdfe7dc352907fc980b868725387e986e649604f74c414a7c2dbe5ef4cc4e75","name":"path_provider_foundation_privacy.bundle","type":"product"},"productTypeIdentifier":"com.apple.product-type.bundle","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":0}],"type":"standard"}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e983b4389e41a26a4fc852e2feb08c32b31","buildSettings":{"ASSETCATALOG_COMPILER_APPICON_NAME":"AppIcon","ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME":"AccentColor","CLANG_ENABLE_OBJC_WEAK":"NO","ENABLE_BITCODE":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_MICROPHONE=1 PERMISSION_SPEECH_RECOGNIZER=1","IPHONEOS_DEPLOYMENT_TARGET":"13.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks","ONLY_ACTIVE_ARCH":"NO","OTHER_LDFLAGS":"$(inherited) -framework AudioToolbox -framework AVFoundation -framework Speech","SDKROOT":"iphoneos","TARGETED_DEVICE_FAMILY":"1,2"},"guid":"bfdfe7dc352907fc980b868725387e982cf0da236cf10d087750aa1434da9227","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e980eb0dfc45486a9a195a5a19657d4bdde","buildSettings":{"ASSETCATALOG_COMPILER_APPICON_NAME":"AppIcon","ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME":"AccentColor","CLANG_ENABLE_OBJC_WEAK":"NO","ENABLE_BITCODE":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_MICROPHONE=1 PERMISSION_SPEECH_RECOGNIZER=1","IPHONEOS_DEPLOYMENT_TARGET":"13.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks","OTHER_LDFLAGS":"$(inherited) -framework AudioToolbox -framework AVFoundation -framework Speech","SDKROOT":"iphoneos","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES"},"guid":"bfdfe7dc352907fc980b868725387e98cc28f154213fd8181aa70d4c188a8335","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e980eb0dfc45486a9a195a5a19657d4bdde","buildSettings":{"ASSETCATALOG_COMPILER_APPICON_NAME":"AppIcon","ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME":"AccentColor","CLANG_ENABLE_OBJC_WEAK":"NO","ENABLE_BITCODE":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","GCC_PREPROCESSOR_DEFINITIONS":"$(inherited) PERMISSION_MICROPHONE=1 PERMISSION_SPEECH_RECOGNIZER=1","IPHONEOS_DEPLOYMENT_TARGET":"13.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks","OTHER_LDFLAGS":"$(inherited) -framework AudioToolbox -framework AVFoundation -framework Speech","SDKROOT":"iphoneos","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES"},"guid":"bfdfe7dc352907fc980b868725387e981f19fefc6e52ad9e4e005a2248234387","name":"Release"}],"buildPhases":[],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e989da425bb6d6d5d8dbb95e4afffb82217","name":"Flutter","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"","configurationName":"Release","provisioningStyle":0}],"type":"aggregate"}

View File

@ -0,0 +1 @@
{"guid":"dc4b70c03e8043e50e38f2068887b1d4","name":"Pods","path":"/Users/max/SourceCode/yuanxuan/yx_speech_to_text_flutter/example/ios/Pods/Pods.xcodeproj/project.xcworkspace","projects":["PROJECT@v11_mod=7f6a4f64a6e2fd3720afe00c8dd0402f_hash=bfdfe7dc352907fc980b868725387e98plugins=1OJSG6M1FOV3XYQCBH7Z29RZ0FPR9XDE1"]}

View File

@ -15,7 +15,7 @@ class MyApp extends StatelessWidget {
title: 'YX ASR Example',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
useMaterial3: true,
useMaterial3: false, // Material 3
),
home: const SpeechRecognitionPage(),
);
@ -42,6 +42,9 @@ class _SpeechRecognitionPageState extends State<SpeechRecognitionPage> {
String _errorMessage = '';
List<String> _recognitionHistory = [];
///
String _baseText = '';
//
final List<String> _realtimeResults = []; //
@ -95,8 +98,6 @@ class _SpeechRecognitionPageState extends State<SpeechRecognitionPage> {
if (result.recognizedWords.isNotEmpty) {
print('📱 [Example] 实时识别: ${result.recognizedWords}');
_currentText = result.recognizedWords;
//
_updateTextController();
}
});
});
@ -157,77 +158,12 @@ class _SpeechRecognitionPageState extends State<SpeechRecognitionPage> {
_recognitionHistory.clear();
_realtimeResults.clear();
_currentText = '';
_baseText = ''; //
_textController.clear();
_errorMessage = '';
});
}
///
void _updateTextController() {
//
final confirmedText = _realtimeResults.join(' ');
final displayText = _currentText.isNotEmpty
? '$confirmedText ${_currentText}'.trim()
: confirmedText;
//
if (_textController.text != displayText) {
final cursorPosition = _textController.selection.baseOffset;
_textController.text = displayText;
//
if (cursorPosition <= displayText.length) {
_textController.selection = TextSelection.fromPosition(
TextPosition(offset: cursorPosition),
);
} else {
_textController.selection = TextSelection.fromPosition(
TextPosition(offset: displayText.length),
);
}
}
}
///
Future<void> _toggleRecording() async {
if (!_isInitialized) return;
try {
if (_isListening) {
print('📱 [Example] 停止录音');
await _speechService.stopListening();
//
if (_currentText.isNotEmpty) {
setState(() {
_realtimeResults.add(_currentText);
_recognitionHistory.insert(0, _currentText);
print('📱 [Example] 添加到历史记录: $_currentText');
//
if (_recognitionHistory.length > 10) {
_recognitionHistory.removeLast();
}
//
_currentText = '';
_updateTextController();
});
}
} else {
print('📱 [Example] 开始录音');
//
setState(() {
_realtimeResults.clear();
_currentText = '';
_textController.clear();
});
await _speechService.startListening(partialResults: true);
}
} catch (e) {
print('📱 [Example] 录音操作失败: $e');
_showErrorSnackBar('录音操作失败: $e');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
@ -427,13 +363,17 @@ class _SpeechRecognitionPageState extends State<SpeechRecognitionPage> {
children: [
Icon(Icons.mic, size: 14, color: Colors.blue[600]),
const SizedBox(width: 4),
Text(
'实时识别中...',
Flexible(
child: Text(
_currentText.isEmpty ? '实时识别中...' : _currentText,
style: TextStyle(
fontSize: 12,
color: Colors.blue[600],
fontWeight: FontWeight.w500,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
),
],
),
@ -526,44 +466,74 @@ class _SpeechRecognitionPageState extends State<SpeechRecognitionPage> {
);
}
return GestureDetector(
onTap: () {
//
HapticFeedback.mediumImpact();
_toggleRecording();
// 使 RecordingButton
return RecordingButton(
speechService: _speechService,
size: 80,
onResult: (result) {
print(
'📱 [Example] RecordingButton 接收到识别结果: "${result.recognizedWords}"');
setState(() {
if (result.recognizedWords.isNotEmpty) {
//
print('📱 [Example] 实时识别,更新输入框: ${result.recognizedWords}');
_currentText = result.recognizedWords;
// = +
String newText = _baseText;
if (newText.isNotEmpty &&
!newText.endsWith(' ') &&
_currentText.isNotEmpty) {
newText += ' '; //
}
newText += _currentText;
_textController.text = newText;
//
_textController.selection = TextSelection.fromPosition(
TextPosition(offset: newText.length),
);
}
});
},
child: Container(
width: 80,
height: 80,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: _isListening
? [Colors.red.shade400, Colors.red.shade600]
: [Colors.blue.shade400, Colors.blue.shade600],
),
boxShadow: [
BoxShadow(
color: (_isListening ? Colors.red : Colors.blue)
.withValues(alpha: 0.4),
spreadRadius: 4,
blurRadius: 12,
offset: const Offset(0, 6),
),
],
),
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child: Icon(
_isListening ? Icons.stop_rounded : Icons.mic_rounded,
key: ValueKey(_isListening),
size: 32,
color: Colors.white,
),
),
),
onError: (error) {
setState(() {
_errorMessage = error.errorMsg;
});
_showErrorSnackBar('识别错误: ${error.errorMsg}');
},
onListeningStatusChanged: (isListening) {
setState(() {
_isListening = isListening;
});
if (!isListening) {
//
if (_currentText.isNotEmpty) {
setState(() {
_recognitionHistory.insert(0, _currentText);
//
if (_recognitionHistory.length > 10) {
_recognitionHistory.removeLast();
}
});
}
//
setState(() {
_baseText = _textController.text; //
_currentText = ''; //
});
} else {
//
setState(() {
_baseText = _textController.text; //
_realtimeResults.clear();
_currentText = ''; //
});
}
},
tooltip: _isListening ? '点击停止录音' : '点击开始录音',
enabled: _isInitialized,
);
}
}

View File

@ -572,29 +572,8 @@ class YxAsrService implements SpeechRecognitionService {
//
await _stopAudioRecording();
//
if (_recognizer != null && _stream != null) {
try {
// 线使
debugPrint('🛑 [YxAsr] 获取流式识别最终结果...');
final result = _recognizer!.getResult(_stream!);
debugPrint('🛑 [YxAsr] 流式最终结果: "${result.text}"');
if (result.text.isNotEmpty) {
debugPrint('📤 [YxAsr] 发送流式最终结果: ${result.text}');
_sendResult(
recognizedWords: result.text,
confidence: 1.0,
alternatives: [],
);
} else {
debugPrint('⚠️ [YxAsr] 流式最终结果为空');
}
} catch (e) {
debugPrint('⚠️ [YxAsr] 获取最终结果时出错: $e');
}
//
if (_stream != null) {
_stream = null;
}