import 'package:ffmpeg_kit_flutter_audio/ffmpeg_kit.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:path_provider/path_provider.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:mobile_scanner/mobile_scanner.dart'; import 'package:flutter_sound/flutter_sound.dart'; import 'package:permission_handler/permission_handler.dart'; import 'dart:io'; import '../../app/constant.dart'; import '../../provider/voice_to_text_provider.dart'; class RekamScreen extends HookConsumerWidget { const RekamScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { SystemChrome.setEnabledSystemUIMode( SystemUiMode.manual, overlays: [SystemUiOverlay.bottom], ); final isRekam = useState(false); final judulTombol = useState("MULAI REKAM"); final qrCodeStr = useState(""); final isSelesaiRekam = useState(false); final audioPath = useState(""); final recorder = useState(FlutterSoundRecorder()); final player = useState(FlutterSoundPlayer()); Future requestPermissions() async { await Permission.microphone.request(); await Permission.storage.request(); } useEffect(() { Future initRecorder() async { await requestPermissions(); await recorder.value.openRecorder(); await player.value.openPlayer(); } initRecorder(); return () { recorder.value.closeRecorder(); player.value.closePlayer(); }; }, []); void handleBarcode(BarcodeCapture barcodes) { if (barcodes.barcodes.isNotEmpty) { final scannedBarcode = barcodes.barcodes.firstOrNull?.displayValue ?? ""; if (scannedBarcode.isNotEmpty) { ref.read(barcodeX.notifier).state = barcodes.barcodes.first; qrCodeStr.value = scannedBarcode; } } } Future jalankanRekaman() async { try { final dir = await getApplicationDocumentsDirectory(); final filePath = '${dir.path}/myFile.aac'; // final filePath = '${dir.path}/myFile.mp3'; audioPath.value = filePath; await recorder.value.startRecorder( toFile: filePath, ); judulTombol.value = "SELESAI"; isSelesaiRekam.value = true; } catch (e) { print("Error start record ${e.toString()}"); } } Future convertToMp3(String inputPath) async { final dir = await getApplicationDocumentsDirectory(); final outputPath = "${dir.path}/output.mp3"; // Jalankan perintah FFmpeg untuk konversi await FFmpegKit.execute( '-i $inputPath -codec:a libmp3lame -qscale:a 2 $outputPath'); // Pastikan file MP3 berhasil dibuat if (File(outputPath).existsSync()) { return outputPath; } else { return null; } } Future berhentiRekaman() async { try { await recorder.value.stopRecorder(); isSelesaiRekam.value = false; isRekam.value = false; // panggil fungsi untuk kirim ke BE if (audioPath.value.isNotEmpty) { String? mp3Path = await convertToMp3(audioPath.value); if (mp3Path != null) { // await uploadAudioFile(mp3Path); print('mp3 convert $mp3Path'); } else { print("Konversi gagal!"); } } } catch (e) { print("Error stop record ${e.toString()}"); } } Future playRecording() async { try { if (audioPath.value.isNotEmpty && File(audioPath.value).existsSync()) { await player.value.startPlayer(fromURI: audioPath.value); } else { print("Error: Path rekaman kosong atau tidak ditemukan."); } } catch (e) { print("Error saat memutar rekaman: ${e.toString()}"); } } return Scaffold( backgroundColor: Constant.bgGrey, bottomNavigationBar: BottomAppBar( color: Colors.blueGrey.shade100, height: Constant.getActualYPhone(context: context, y: 100), shape: const CircularNotchedRectangle(), child: Row( children: [ ElevatedButton.icon( onPressed: () { ref.read(barcodeX.notifier).state = Barcode(); isRekam.value = false; judulTombol.value = "MULAI REKAM"; qrCodeStr.value = ""; isSelesaiRekam.value = false; Navigator.of(context).pop(); }, icon: Icon(Icons.arrow_back, size: 17, color: Constant.textWhite), label: Text( 'Kembali', style: Constant.cardText(context: context) .copyWith(color: Constant.textWhite), ), style: ElevatedButton.styleFrom( backgroundColor: Colors.green.shade400, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), elevation: 8, ), ), const Spacer(), ElevatedButton( onPressed: qrCodeStr.value.isEmpty ? null : () async { if (!isSelesaiRekam.value) { await jalankanRekaman(); } else { await berhentiRekaman(); } }, style: ElevatedButton.styleFrom( backgroundColor: qrCodeStr.value.isNotEmpty ? Constant.bgButton : Constant.bgGrey, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), elevation: 8, ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.mic, size: 20, color: Constant.textWhite), SizedBox(width: 10), Text( judulTombol.value, style: Constant.titleButton500(context: context) .copyWith(color: Constant.textWhite), ), ], ), ), ], ), ), appBar: AppBar( title: Text( 'Rekam Audio', style: Constant.titlePosisiHP(context: context), ), automaticallyImplyLeading: false, ), body: Padding( padding: EdgeInsets.symmetric(horizontal: 20), child: Column( children: [ if (!isRekam.value) SizedBox( width: double.infinity, height: Constant.getActualYPhone( context: context, y: 450, ), child: MobileScanner(onDetect: handleBarcode), ), SizedBox( height: Constant.getActualYPhone( context: context, y: 20, ), ), Container( alignment: Alignment.center, padding: EdgeInsets.symmetric(vertical: 10), color: Constant.inputanGrey, child: Text("Info: ${qrCodeStr.value}", style: TextStyle(color: Colors.white)), ), SizedBox(height: 40), ElevatedButton(onPressed: playRecording, child: Text('Play')), ], ), ), ); } }