Skip to content

Commit

Permalink
Merge branch 'GDSC-DGU:develop' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
bunju20 authored Feb 20, 2024
2 parents 8e1c2e5 + 5f3dfdc commit 1643e50
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 61 deletions.
6 changes: 0 additions & 6 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -634,8 +634,6 @@ PODS:
- AppAuth/Core (1.6.2)
- AppAuth/ExternalUserAgent (1.6.2):
- AppAuth/Core
- audioplayers_darwin (0.0.1):
- Flutter
- BoringSSL-GRPC (0.0.24):
- BoringSSL-GRPC/Implementation (= 0.0.24)
- BoringSSL-GRPC/Interface (= 0.0.24)
Expand Down Expand Up @@ -842,7 +840,6 @@ PODS:
- FlutterMacOS

DEPENDENCIES:
- audioplayers_darwin (from `.symlinks/plugins/audioplayers_darwin/ios`)
- cloud_firestore (from `.symlinks/plugins/cloud_firestore/ios`)
- firebase_auth (from `.symlinks/plugins/firebase_auth/ios`)
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
Expand Down Expand Up @@ -890,8 +887,6 @@ SPEC REPOS:
- Try

EXTERNAL SOURCES:
audioplayers_darwin:
:path: ".symlinks/plugins/audioplayers_darwin/ios"
cloud_firestore:
:path: ".symlinks/plugins/cloud_firestore/ios"
firebase_auth:
Expand Down Expand Up @@ -928,7 +923,6 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
abseil: 926fb7a82dc6d2b8e1f2ed7f3a718bce691d1e46
AppAuth: 3bb1d1cd9340bd09f5ed189fb00b1cc28e1e8570
audioplayers_darwin: 877d9a4d06331c5c374595e46e16453ac7eafa40
BoringSSL-GRPC: 3175b25143e648463a56daeaaa499c6cb86dad33
cloud_firestore: ba576bee785a05ff952e4da7fa4e23c196917436
Firebase: 10c8cb12fb7ad2ae0c09ffc86cd9c1ab392a0031
Expand Down
13 changes: 13 additions & 0 deletions lib/models/record_word_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class RecordWordModel {
final String pronunciation;
final int similarity;

RecordWordModel({required this.pronunciation, required this.similarity});

factory RecordWordModel.fromJson(Map<String, dynamic> json) {
return RecordWordModel(
pronunciation: json['pronunciation'],
similarity: json['similarity'],
);
}
}
114 changes: 114 additions & 0 deletions lib/viewModels/record/record_viewmodel.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import 'dart:convert';

import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:get/get.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'package:http/http.dart' as http;
import 'package:path_provider/path_provider.dart';

class RecordViewModel extends GetxController {
final FlutterSoundRecorder _audioRecorder = FlutterSoundRecorder();

final RxBool isRecording = false.obs;
RxString audioFilePath = ''.obs;
final RxMap<String, dynamic> response =
<String, dynamic>{}.obs; // Specify the types

@override
void onInit() {
_requestPermission();
super.onInit();
}

Future<void> _requestPermission() async {
var microphoneStatus = await Permission.microphone.status;
if (!microphoneStatus.isGranted) {
await Permission.microphone.request();
}
}

Future<void> _startRecording() async {
if (isRecording.value) return;

// Ensure the recorder is open
if (!_audioRecorder.isStopped) {
await _audioRecorder.closeRecorder();
}

// Open the recorder
await _audioRecorder.openRecorder();
final directory = await getApplicationDocumentsDirectory();
final filePath =
'${directory.path}/${DateTime.now().millisecondsSinceEpoch}.aac';

print('Recording to $filePath');
try {
await _audioRecorder.startRecorder(
toFile: filePath,
codec: Codec.aacADTS,
);

isRecording.value = true;
} catch (e) {
print('Error starting recorder: $e');
// Handle the error as needed
}
}

Future<String?> _stopRecording() async {
try {
final path = await _audioRecorder.stopRecorder();
audioFilePath.value = path!;
isRecording.value = false;
return path; // 녹음이 중지된 파일의 경로를 반환합니다.
} catch (e) {}
return null;
}

Future<void> sendTextAndAudio(String content) async {
String url = '${dotenv.env['API_URL']!}/study/syllable';
print('Sending data and audio to $url');
print('audioFilePath.value: ${audioFilePath.value}');
print('content: $content');
if (audioFilePath.value.isEmpty) {
print('Audio file is not available.');
return;
}

try {
var request = http.MultipartRequest('POST', Uri.parse(url))
..fields['content'] = content
..files.add(
await http.MultipartFile.fromPath('audio', audioFilePath.value));

print('Sending data and audio...----------------------------');
var response = await request.send();
if (response.statusCode == 200) {
// Read the response stream and convert it to a JSON object
final respStr = await response.stream.bytesToString();
final jsonResponse = json.decode(respStr);

// Store the response in the RxMap
this.response.value = jsonResponse;
} else {
print(
'Failed to send data and audio. Status code: ${response.statusCode}',
);
}
} catch (e) {
print(e.toString());
}
}

void toggleRecording() async {
isRecording.value ? await _stopRecording() : await _startRecording();
update();
}

@override
void onClose() {
_audioRecorder.closeRecorder();
super.onClose();
}
}
35 changes: 14 additions & 21 deletions lib/viewModels/script/create_script_viewmodel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,22 @@ import 'package:permission_handler/permission_handler.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:async';
import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:earlips/views/script/analyze_screen.dart';
import 'package:earlips/viewModels/script/analyze_viewmodel.dart';



class CreateScriptViewModel extends ChangeNotifier {
bool isRecording = false;
bool _isRecorderInitialized = false; // 녹음기 초기화 여부 : 파일
bool _isRecording = false; // 녹음 중 여부 : 파일
FlutterSoundRecorder? _audioRecorder;
String audioFilePath = '';


bool handDone = false;
TextEditingController writedTextController = TextEditingController(); // 사용자 입력을 위한 컨트롤러
TextEditingController voicedTextController = TextEditingController(); // 음성 인식 결과를 위한 컨트롤러
TextEditingController writedTextController =
TextEditingController(); // 사용자 입력을 위한 컨트롤러
TextEditingController voicedTextController =
TextEditingController(); // 음성 인식 결과를 위한 컨트롤러
stt.SpeechToText speechToText = stt.SpeechToText();

CreateScriptViewModel() {
Expand Down Expand Up @@ -53,9 +51,8 @@ class CreateScriptViewModel extends ChangeNotifier {
if (!_isRecorderInitialized || _isRecording) return;

final directory = await getApplicationDocumentsDirectory();
final filePath = '${directory.path}/${DateTime
.now()
.millisecondsSinceEpoch}.aac';
final filePath =
'${directory.path}/${DateTime.now().millisecondsSinceEpoch}.aac';

await _audioRecorder!.startRecorder(
toFile: filePath,
Expand All @@ -78,9 +75,7 @@ class CreateScriptViewModel extends ChangeNotifier {
}
}


Future<void> sendTextAndAudio() async {

String url = dotenv.env['SCRIPT_API'].toString();
String textToSend = writedTextController.text;
if (audioFilePath.isEmpty) {
Expand All @@ -91,7 +86,8 @@ class CreateScriptViewModel extends ChangeNotifier {
try {
var request = http.MultipartRequest('POST', Uri.parse(url))
..fields['content'] = textToSend // 'content' 필드 이름으로 수정
..files.add(await http.MultipartFile.fromPath('audio', audioFilePath)); // 'audio' 필드 이름은 그대로 유지
..files.add(await http.MultipartFile.fromPath(
'audio', audioFilePath)); // 'audio' 필드 이름은 그대로 유지

var response = await request.send();
if (response.statusCode == 200) {
Expand All @@ -115,21 +111,19 @@ class CreateScriptViewModel extends ChangeNotifier {
print('Received null or invalid data from the server.');
}
} else {
print('Failed to send data and audio. Status code: ${response.statusCode}');
print(
'Failed to send data and audio. Status code: ${response.statusCode}');
}
} catch (e) {
print(e.toString());
}
}




void _handleStatus(String status) {
if (handDone) return;
if (status == 'done') {
stopListening();
Future.delayed(Duration(milliseconds: 100), () {
Future.delayed(const Duration(milliseconds: 100), () {
startListening();
});
}
Expand Down Expand Up @@ -160,12 +154,12 @@ class CreateScriptViewModel extends ChangeNotifier {
speechToText.listen(
onResult: (result) {
if (result.finalResult) {
voicedTextController.text += result.recognizedWords + " ";
voicedTextController.text += "${result.recognizedWords} ";
notifyListeners();
}
},
listenFor: Duration(minutes: 5),
pauseFor: Duration(seconds: 3),
listenFor: const Duration(minutes: 5),
pauseFor: const Duration(seconds: 3),
);
}

Expand All @@ -179,7 +173,6 @@ class CreateScriptViewModel extends ChangeNotifier {
await sendTextAndAudio(); // 비동기 호출로 수정
}


@override
void dispose() {
// 컨트롤러들을 정리합니다.
Expand Down
1 change: 0 additions & 1 deletion lib/views/word/widget/word_list_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ class _WordListState extends State<WordList> {
itemCount: widget.wordDataList.length,
onPageChanged: (index) {
wordViewModel.currentIndex.value = index;
print('currentIndex: ${wordViewModel.currentIndex.value}');
},
itemBuilder: (context, index) {
final wordData = widget.wordDataList[index];
Expand Down
Loading

0 comments on commit 1643e50

Please sign in to comment.