Files
Adminator 1e51ef7def Nachtrag: alle bisher untracked Ordner + hängende Änderungen mit-committen
- Konzept/, didaktik_geografie/, didaktik_simulation/, v2-modules/, v2-platform/
- 12 code-workspace-Files
- STATUS-*.md
- viele M/D/R-Änderungen an bereits getrackten Files
- .gitignore verstärkt: **/.humaninput/, **/secret_keys.txt

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-08 02:27:02 +02:00

87 lines
3.0 KiB
PHP

<?php
/**
* Atlas-Tool: Sprachausgabe generieren mit ElevenLabs.
*
* NUR LOKAL ausführen. API-Key liegt in v2-platform/.env.local.
*
* Aufruf:
* php voice.php --text "..." --voice <pool-id> --output path/to/file.mp3 [--dry-run]
*
* Stimmen-Pool-IDs sind in voices.json zentral gepflegt. Module geben
* Pool-ID an (z.B. "narrator-warm"), nicht direkt ElevenLabs-IDs.
*
* Status: Skelett — echte API-Call-Implementierung folgt.
*/
declare(strict_types=1);
require_once __DIR__ . '/../../php/config.php';
$opts = getopt('', ['text:', 'voice:', 'output:', 'dry-run']);
if (empty($opts['text']) || empty($opts['voice']) || empty($opts['output'])) {
fwrite(STDERR, "Usage: php voice.php --text \"...\" --voice <pool-id> --output path.mp3 [--dry-run]\n");
exit(1);
}
$text = $opts['text'];
$voicePoolId = $opts['voice'];
$output = $opts['output'];
$dryRun = isset($opts['dry-run']);
// === Pool-ID → ElevenLabs-ID auflösen ===
$voicesFile = __DIR__ . '/voices.json';
if (!file_exists($voicesFile)) {
fwrite(STDERR, "[asset-gen/voice] FEHLER: voices.json fehlt in tools/asset-gen/\n");
exit(2);
}
$voices = json_decode(file_get_contents($voicesFile), true);
if (!isset($voices[$voicePoolId])) {
fwrite(STDERR, "[asset-gen/voice] FEHLER: Pool-ID '$voicePoolId' nicht in voices.json definiert.\n");
fwrite(STDERR, " Verfügbar: " . implode(', ', array_keys($voices)) . "\n");
exit(2);
}
$elevenlabsId = $voices[$voicePoolId]['elevenlabs_id'];
echo "[asset-gen/voice] Text: " . substr($text, 0, 80) . (strlen($text) > 80 ? '…' : '') . "\n";
echo "[asset-gen/voice] Pool-ID: $voicePoolId\n";
echo "[asset-gen/voice] ElevenLabs: $elevenlabsId\n";
echo "[asset-gen/voice] Output: $output\n";
if (empty(V2_ELEVENLABS_KEY)) {
fwrite(STDERR, "[asset-gen/voice] FEHLER: ELEVENLABS_API_KEY nicht gesetzt.\n");
exit(2);
}
if ($dryRun) {
echo "[asset-gen/voice] --dry-run, würde TTS generieren.\n";
exit(0);
}
// === TODO: echter API-Call ===
// $url = "https://api.elevenlabs.io/v1/text-to-speech/$elevenlabsId";
// $ch = curl_init($url);
// curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// curl_setopt($ch, CURLOPT_HTTPHEADER, [
// 'xi-api-key: ' . V2_ELEVENLABS_KEY,
// 'Content-Type: application/json',
// 'Accept: audio/mpeg',
// ]);
// curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
// 'text' => $text,
// 'model_id' => 'eleven_multilingual_v2',
// 'voice_settings' => ['stability' => 0.55, 'similarity_boost' => 0.75],
// ]));
// $audio = curl_exec($ch);
// $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
// curl_close($ch);
// if ($code === 200 && $audio) {
// @mkdir(dirname($output), 0775, true);
// file_put_contents($output, $audio);
// echo "[asset-gen/voice] OK: gespeichert nach $output\n";
// exit(0);
// }
// fwrite(STDERR, "[asset-gen/voice] FEHLER: HTTP $code\n");
// exit(3);
fwrite(STDERR, "[asset-gen/voice] HINWEIS: Echter API-Call noch nicht implementiert. Stub liefert nichts.\n");
exit(0);