feat: self-hosted Whisper server support
- MediaTranscriber: if whisper_url set, POSTs to own server with Basic auth (audio_file field); falls back to OpenAI cloud Whisper - Admin AI tab: new section for whisper_url / whisper_user / whisper_pass - save-ai endpoint: saves the three whisper fields to config_json Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
9509c3b4fc
commit
fc54ec992b
@@ -69,13 +69,48 @@ class MediaTranscriber
|
||||
|
||||
private static function whisper(string $bytes, string $mime, array $cfg): ?string
|
||||
{
|
||||
$apiKey = $cfg['openai_api_key'] ?? env('OPENAI_API_KEY', '');
|
||||
if ($apiKey === '') return null;
|
||||
|
||||
$ext = str_contains($mime, 'ogg') ? 'ogg' : (str_contains($mime, 'mp4') ? 'mp4' : 'ogg');
|
||||
$tmpFile = tempnam(sys_get_temp_dir(), 'wa_audio_') . '.' . $ext;
|
||||
file_put_contents($tmpFile, $bytes);
|
||||
|
||||
$whisperUrl = trim($cfg['whisper_url'] ?? '');
|
||||
$whisperUser = trim($cfg['whisper_user'] ?? '');
|
||||
$whisperPass = trim($cfg['whisper_pass'] ?? '');
|
||||
$useOwn = $whisperUrl !== '';
|
||||
|
||||
if ($useOwn) {
|
||||
$t0 = (int)(microtime(true) * 1000);
|
||||
$ch = curl_init($whisperUrl);
|
||||
$opts = [
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => ['audio_file' => new CURLFile($tmpFile, $mime, 'audio.' . $ext)],
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TIMEOUT => 120,
|
||||
];
|
||||
if ($whisperUser !== '') {
|
||||
$opts[CURLOPT_USERPWD] = "{$whisperUser}:{$whisperPass}";
|
||||
}
|
||||
curl_setopt_array($ch, $opts);
|
||||
$resp = curl_exec($ch);
|
||||
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
$ms = (int)(microtime(true) * 1000) - $t0;
|
||||
@unlink($tmpFile);
|
||||
|
||||
if ($code !== 200 || !$resp) return null;
|
||||
|
||||
// Respuesta puede ser JSON {"text":"..."} o texto plano
|
||||
$data = json_decode($resp, true);
|
||||
$text = is_array($data) ? trim($data['text'] ?? '') : trim($resp);
|
||||
if ($text === '') return null;
|
||||
AiLogger::log($cfg['__company_id'] ?? null, 'whisper-own', 'whisper', 'transcribe', '[audio]', $text, $ms);
|
||||
return $text;
|
||||
}
|
||||
|
||||
// Fallback: OpenAI cloud Whisper
|
||||
$apiKey = $cfg['openai_api_key'] ?? env('OPENAI_API_KEY', '');
|
||||
if ($apiKey === '') { @unlink($tmpFile); return null; }
|
||||
|
||||
$t0 = (int)(microtime(true) * 1000);
|
||||
$ch = curl_init('https://api.openai.com/v1/audio/transcriptions');
|
||||
curl_setopt_array($ch, [
|
||||
|
||||
Reference in New Issue
Block a user