Update: 2026-05-07 18:27:10
This commit is contained in:
@@ -49,7 +49,11 @@ if ($rawAudio === false) {
|
|||||||
}
|
}
|
||||||
$base64Audio = base64_encode($rawAudio);
|
$base64Audio = base64_encode($rawAudio);
|
||||||
|
|
||||||
$mimeType = detectAudioMimeType($tmpPath, (string)($audio['type'] ?? 'audio/m4a'));
|
$mimeType = detectAudioMimeType(
|
||||||
|
$tmpPath,
|
||||||
|
(string)($audio['type'] ?? ''),
|
||||||
|
(string)($audio['name'] ?? '')
|
||||||
|
);
|
||||||
$intent = extractIntentFromAudio($base64Audio, $mimeType, $geminiApiKey);
|
$intent = extractIntentFromAudio($base64Audio, $mimeType, $geminiApiKey);
|
||||||
$execution = executeVoiceAction($decoded, $intent);
|
$execution = executeVoiceAction($decoded, $intent);
|
||||||
|
|
||||||
@@ -58,19 +62,17 @@ json_success([
|
|||||||
'execution' => $execution,
|
'execution' => $execution,
|
||||||
], 'تم تحليل الأمر الصوتي وتنفيذه');
|
], 'تم تحليل الأمر الصوتي وتنفيذه');
|
||||||
|
|
||||||
function detectAudioMimeType(string $path, string $fallback): string
|
function detectAudioMimeType(string $path, string $fallback, string $fileName = ''): string
|
||||||
{
|
{
|
||||||
$allowed = [
|
$allowed = [
|
||||||
'audio/mpeg',
|
|
||||||
'audio/mp3',
|
'audio/mp3',
|
||||||
'audio/mp4',
|
'audio/mpeg',
|
||||||
'audio/m4a',
|
|
||||||
'audio/wav',
|
'audio/wav',
|
||||||
'audio/x-wav',
|
'audio/x-wav',
|
||||||
'audio/webm',
|
'audio/aiff',
|
||||||
'audio/ogg',
|
|
||||||
'audio/aac',
|
'audio/aac',
|
||||||
'audio/x-m4a',
|
'audio/ogg',
|
||||||
|
'audio/flac',
|
||||||
];
|
];
|
||||||
|
|
||||||
$detected = $fallback;
|
$detected = $fallback;
|
||||||
@@ -85,8 +87,13 @@ function detectAudioMimeType(string $path, string $fallback): string
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep a safe supported fallback for Gemini audio understanding.
|
if ($detected === 'audio/x-wav' || str_ends_with(strtolower($fileName), '.wav')) {
|
||||||
return in_array($detected, $allowed, true) ? $detected : 'audio/m4a';
|
return 'audio/wav';
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Flutter recorder now sends WAV. If the server cannot detect the part
|
||||||
|
// MIME type, use a Gemini-supported fallback instead of m4a/mp4.
|
||||||
|
return in_array($detected, $allowed, true) ? $detected : 'audio/wav';
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractIntentFromAudio(string $base64Audio, string $mimeType, string $apiKey): array
|
function extractIntentFromAudio(string $base64Audio, string $mimeType, string $apiKey): array
|
||||||
|
|||||||
@@ -251,14 +251,13 @@ class DashboardController extends GetxController {
|
|||||||
|
|
||||||
final tempDir = await getTemporaryDirectory();
|
final tempDir = await getTemporaryDirectory();
|
||||||
final path =
|
final path =
|
||||||
'${tempDir.path}/voice_${DateTime.now().millisecondsSinceEpoch}.m4a';
|
'${tempDir.path}/voice_${DateTime.now().millisecondsSinceEpoch}.wav';
|
||||||
|
|
||||||
await _audioRecorder.start(
|
await _audioRecorder.start(
|
||||||
const RecordConfig(
|
const RecordConfig(
|
||||||
encoder: AudioEncoder.aacLc,
|
encoder: AudioEncoder.wav,
|
||||||
sampleRate: 16000,
|
sampleRate: 16000,
|
||||||
numChannels: 1,
|
numChannels: 1,
|
||||||
bitRate: 64000,
|
|
||||||
),
|
),
|
||||||
path: path,
|
path: path,
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user