56 lines
1.8 KiB
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]);
|
|
}
|
|
}
|