Update: 2026-05-07 18:29:37
This commit is contained in:
@@ -11,10 +11,20 @@ class VoiceAssistantService {
|
|||||||
Future<Map<String, dynamic>> processVoiceCommand(File audioFile) async {
|
Future<Map<String, dynamic>> processVoiceCommand(File audioFile) async {
|
||||||
final fileName = audioFile.uri.pathSegments.isNotEmpty
|
final fileName = audioFile.uri.pathSegments.isNotEmpty
|
||||||
? audioFile.uri.pathSegments.last
|
? audioFile.uri.pathSegments.last
|
||||||
: 'voice_command.m4a';
|
: 'voice_command.wav';
|
||||||
|
final mimeType = _mimeTypeForFileName(fileName);
|
||||||
|
final fileSize = await audioFile.length();
|
||||||
|
|
||||||
|
AppLogger.print(
|
||||||
|
'Voice upload file=$fileName, bytes=$fileSize, mime=$mimeType, path=${audioFile.path}',
|
||||||
|
);
|
||||||
|
|
||||||
final formData = FormData.fromMap({
|
final formData = FormData.fromMap({
|
||||||
'audio': await MultipartFile.fromFile(audioFile.path, filename: fileName),
|
'audio': await MultipartFile.fromFile(
|
||||||
|
audioFile.path,
|
||||||
|
filename: fileName,
|
||||||
|
contentType: DioMediaType.parse(mimeType),
|
||||||
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
final response = await _dio.post(
|
final response = await _dio.post(
|
||||||
@@ -40,4 +50,14 @@ class VoiceAssistantService {
|
|||||||
AppLogger.print('Voice API success: ${body['message']}');
|
AppLogger.print('Voice API success: ${body['message']}');
|
||||||
return Map<String, dynamic>.from(payload);
|
return Map<String, dynamic>.from(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _mimeTypeForFileName(String fileName) {
|
||||||
|
final lower = fileName.toLowerCase();
|
||||||
|
if (lower.endsWith('.wav')) return 'audio/wav';
|
||||||
|
if (lower.endsWith('.flac')) return 'audio/flac';
|
||||||
|
if (lower.endsWith('.mp3')) return 'audio/mp3';
|
||||||
|
if (lower.endsWith('.aac')) return 'audio/aac';
|
||||||
|
if (lower.endsWith('.ogg')) return 'audio/ogg';
|
||||||
|
return 'audio/wav';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -250,12 +250,37 @@ class DashboardController extends GetxController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final tempDir = await getTemporaryDirectory();
|
final tempDir = await getTemporaryDirectory();
|
||||||
|
final wavSupported =
|
||||||
|
await _audioRecorder.isEncoderSupported(AudioEncoder.wav);
|
||||||
|
final flacSupported =
|
||||||
|
await _audioRecorder.isEncoderSupported(AudioEncoder.flac);
|
||||||
|
|
||||||
|
final AudioEncoder encoder;
|
||||||
|
final String extension;
|
||||||
|
if (wavSupported) {
|
||||||
|
encoder = AudioEncoder.wav;
|
||||||
|
extension = 'wav';
|
||||||
|
} else if (flacSupported) {
|
||||||
|
encoder = AudioEncoder.flac;
|
||||||
|
extension = 'flac';
|
||||||
|
} else {
|
||||||
|
AppSnackbar.showError(
|
||||||
|
'الصوت',
|
||||||
|
'هذا الجهاز لا يدعم صيغة صوت مناسبة لـ Gemini حالياً',
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final path =
|
final path =
|
||||||
'${tempDir.path}/voice_${DateTime.now().millisecondsSinceEpoch}.wav';
|
'${tempDir.path}/voice_${DateTime.now().millisecondsSinceEpoch}.$extension';
|
||||||
|
|
||||||
|
AppLogger.print(
|
||||||
|
'Voice recorder selected encoder=$encoder, wavSupported=$wavSupported, flacSupported=$flacSupported, path=$path',
|
||||||
|
);
|
||||||
|
|
||||||
await _audioRecorder.start(
|
await _audioRecorder.start(
|
||||||
const RecordConfig(
|
RecordConfig(
|
||||||
encoder: AudioEncoder.wav,
|
encoder: encoder,
|
||||||
sampleRate: 16000,
|
sampleRate: 16000,
|
||||||
numChannels: 1,
|
numChannels: 1,
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user