Skip to content

Commit

Permalink
Merge pull request #130 from MakeFrog/fix/aos-speech-to-text-issue
Browse files Browse the repository at this point in the history
[면접] �AOS speech to text 오류 수정
  • Loading branch information
Xim-ya authored Sep 26, 2024
2 parents 0ae45f6 + 97143e8 commit 3a6c66a
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 42 deletions.
5 changes: 5 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<queries>
<intent>
<action android:name="android.speech.RecognitionService" />
</intent>
</queries>
<application
android:label="@string/app_name"
android:name="${applicationName}"
Expand Down
12 changes: 6 additions & 6 deletions ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.5;
MARKETING_VERSION = 1.0.6;
PRODUCT_BUNDLE_IDENTIFIER = com.techtalk.dev;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
Expand Down Expand Up @@ -585,7 +585,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.5;
MARKETING_VERSION = 1.0.6;
PRODUCT_BUNDLE_IDENTIFIER = com.techtalk.dev;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
Expand Down Expand Up @@ -668,7 +668,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.5;
MARKETING_VERSION = 1.0.6;
PRODUCT_BUNDLE_IDENTIFIER = com.techtalk;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
Expand Down Expand Up @@ -751,7 +751,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.5;
MARKETING_VERSION = 1.0.6;
PRODUCT_BUNDLE_IDENTIFIER = com.techtalk.dev;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
Expand Down Expand Up @@ -891,7 +891,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.5;
MARKETING_VERSION = 1.0.6;
PRODUCT_BUNDLE_IDENTIFIER = com.techtalk;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
Expand Down Expand Up @@ -921,7 +921,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.5;
MARKETING_VERSION = 1.0.6;
PRODUCT_BUNDLE_IDENTIFIER = com.techtalk;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
Expand Down
8 changes: 6 additions & 2 deletions lib/app/environment/flavor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,16 @@ class Flavor {
/// 채팅 면접에서 사용되는 OepnAI SK
OpenAI.instance.build(
token: env.openApiKey,
baseOption: HttpSetup(receiveTimeout: const Duration(seconds: 10), connectTimeout: const Duration(seconds: 10)),
baseOption: HttpSetup(
receiveTimeout: const Duration(seconds: 10),
connectTimeout: const Duration(seconds: 10)),
enableLog: true,
);

/// whisper 모델을 제공하는 OpenAI SDK
forWhisper.OpenAI.apiKey = env.openApiKey;
forWhisper.OpenAI.apiKey = env.openApiKey;
forWhisper.OpenAI.requestsTimeOut = const Duration(seconds: 12);


/// 앱 DI 실행
await AppBinder.init();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class SpeechToTextProvider extends ChangeNotifier with ChatEvent {

/// 음성 녹음 컨트롤러
final recordController = AudioRecorder();
final speechController = SpeechToText();
late final speechController = Platform.isIOS ? SpeechToText() : null;

//// speech 컨트롤러 listen 가능 상태 여부
Completer<void> isSpeechListenAvailable = Completer<void>();
Expand All @@ -42,6 +42,14 @@ class SpeechToTextProvider extends ChangeNotifier with ChatEvent {
/// 음성 녹음 파일이 저장되는 경로
late String recordPath;

/// 아무 음성을 인식하지 않고 whisper 모델을 실행했을 때 발생하는 텍스트\
/// ko버전
final List<String> _ghostWords = [
'MBC 뉴스 이덕영입니다',
'시청해주셔서',
'. .',
];

///
/// 타이핑 모드 버튼 클릭시
///
Expand Down Expand Up @@ -98,20 +106,30 @@ class SpeechToTextProvider extends ChangeNotifier with ChatEvent {
/// 녹음 중지
await recordController.stop();

await isSpeechListenAvailable.future;
if (Platform.isIOS) {
await isSpeechListenAvailable.future;

/// 입력된 텍스트가 없다면 알럿을 노출 후 초기화 상태로 변경
if (notifyText.isEmpty) {
SnackBarService.showSnackBar(tr(LocaleKeys.interview_noAudioDetected));
await File(recordPath).delete();
_updateProgressState(RecordProgressState.initial);
return;
/// 입력된 텍스트가 없다면 알럿을 노출 후 초기화 상태로 변경
if (notifyText.isEmpty) {
SnackBarService.showSnackBar(tr(LocaleKeys.interview_noAudioDetected));
await File(recordPath).delete();
_updateProgressState(RecordProgressState.initial);
return;
}
}

/// 녹음된 텍스트 (Speech To Text)
final recordedText = await recordToTextUseCase.call(recordPath);

await recordedText.fold(onSuccess: (text) async {
if (Platform.isAndroid &&
_ghostWords.any((element) => text.contains(element))) {
SnackBarService.showSnackBar(tr(LocaleKeys.interview_noAudioDetected));
await File(recordPath).delete();
_updateProgressState(RecordProgressState.initial);
return;
}

/// 기존 텍스트 입력폼에 저장되어 있던 텍스트와 녹음된 텍스트 병합
final textFiledController = ref.read(mainInputControllerProvider);
await File(recordPath).delete();
Expand Down Expand Up @@ -164,8 +182,10 @@ class SpeechToTextProvider extends ChangeNotifier with ChatEvent {
if (progressState.isOnProgress || progressState.isReady) {
_updateProgressState(RecordProgressState.loading);
notifyListeners();
unawaited(
Future.wait([recordController.stop(), speechController.cancel()]));
unawaited(Future.wait([
recordController.stop(),
if (Platform.isIOS) speechController!.cancel() else Future.value()
]));
}

_updateProgressState(RecordProgressState.initial, resetText: true);
Expand All @@ -182,9 +202,9 @@ class SpeechToTextProvider extends ChangeNotifier with ChatEvent {
/// SpeechToText 컨트롤러 초기화
///
Future<void> initializeSpeechController() async {
final isEnabled = await speechController.initialize();
final isEnabled = await speechController!.initialize();
if (isEnabled) {
await speechController.listen(onResult: (result) {
await speechController!.listen(onResult: (result) {
if (progressState.isOnProgress) {
notifyText = result.recognizedWords;
notifyListeners();
Expand All @@ -193,7 +213,7 @@ class SpeechToTextProvider extends ChangeNotifier with ChatEvent {

isSpeechListenAvailable.complete(null);
} else {
unawaited(speechController.cancel());
unawaited(speechController!.cancel());
}
}

Expand All @@ -215,7 +235,9 @@ class SpeechToTextProvider extends ChangeNotifier with ChatEvent {
await File(recordPath).delete();
}

await initializeSpeechController();
if (Platform.isIOS) {
await initializeSpeechController();
}
}
}

Expand All @@ -224,7 +246,9 @@ final speechToTextProvider = AutoDisposeChangeNotifierProvider((ref) {
provider.initConfigSettings();

ref.onDispose(() {
provider.speechController.cancel();
if (Platform.isIOS) {
provider.speechController!.cancel();
}
provider.recordController.dispose();
});
return provider;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_svg/flutter_svg.dart';
Expand Down Expand Up @@ -134,24 +136,31 @@ class RoundedMicMotionView extends HookConsumerWidget {
duration: const Duration(milliseconds: 1650),
);

ref.listen(
speechToTextProvider.select(
(p) => p.notifyText), (prev, now) {
if (now.isNotEmpty) {
// 텍스트가 입력되면 애니메이션 반복 실행

if (!animationController.isAnimating) {
animationController.repeat();
}
if (Platform.isIOS) {
ref.listen(
speechToTextProvider.select(
(p) => p.notifyText), (prev, now) {
if (now.isNotEmpty) {
// 텍스트가 입력되면 애니메이션 반복 실행

debouncer.run(() async {
if (animationController.isAnimating) {
await animationController.forward();
animationController.stop();
if (!animationController.isAnimating) {
animationController.repeat();
}
});
}
});

debouncer.run(() async {
if (animationController.isAnimating) {
await animationController.forward();
animationController.stop();
}
});
}
});
} else {
useEffect(() {
animationController.repeat();
return null;
}, []);
}

return StaggeredDotsWave(
size: 24,
Expand Down
10 changes: 8 additions & 2 deletions lib/presentation/widgets/common/dialog/app_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,10 @@ class AppDialog extends Dialog {
),
textStyle: AppTextStyle.title1,
),
child: Text(leftBtnText!),
child: Text(
leftBtnText!,
textAlign: TextAlign.center,
),
),
),
],
Expand All @@ -190,7 +193,10 @@ class AppDialog extends Dialog {
vertical: 13,
),
),
child: Text(btnText!),
child: Text(
btnText!,
textAlign: TextAlign.center,
),
),
)
],
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ description: A new Flutter project.

publish_to: "none"

version: 1.0.5+18
version: 1.0.5+20

environment:
sdk: ">=3.0.6 <4.0.0"
Expand Down

0 comments on commit 3a6c66a

Please sign in to comment.