fox/app/Http/Controllers/FoxVoiceController.php

56 lines
1.8 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Services\SpeechService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Process;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
/**
* Endpoint NUR fürs Transkribieren. Frontend bekommt den Text zurück und
* routet ihn durch den normalen send-Flow (IntentDetector + Livewire).
* NICHT mehr: handleUserMessage / speak() - das würde 2x getriggert + Doppel-Audio.
*/
class FoxVoiceController
{
public function __invoke(Request $request, SpeechService $speech): JsonResponse
{
$upload = $request->file('audio');
if (! $upload) {
return response()->json(['error' => 'no_file', 'detail' => 'audio field missing'], 422);
}
if (! $upload->isValid()) {
return response()->json([
'error' => 'invalid_upload',
'detail' => $upload->getErrorMessage(),
'size' => $upload->getSize(),
], 422);
}
if ($upload->getSize() > 50_000_000) {
return response()->json(['error' => 'too_large', 'size' => $upload->getSize()], 413);
}
// webm/ogg → wav konvertieren (whisper.cpp will 16kHz mono wav)
$rawPath = $upload->getRealPath();
$wavName = 'in_'.Str::random(10).'.wav';
$wavPath = Storage::disk('audio')->path($wavName);
Process::timeout(30)->run(sprintf(
'ffmpeg -y -i %s -ar 16000 -ac 1 -f wav %s 2>&1',
escapeshellarg($rawPath),
escapeshellarg($wavPath),
));
$text = $speech->transcribe($wavPath);
if (! $text) {
return response()->json(['text' => null, 'error' => 'Transkription fehlgeschlagen'], 422);
}
return response()->json(['text' => $text]);
}
}