Síntesis de voz básica
El siguiente talk.php es un ejemplo que sintetiza voz desde texto y la escribe en un archivo WAV.
PHP FFI está normalmente deshabilitado en entornos de servidor web (FPM, etc.). Ejecuta este script desde CLI, con php talk.php.
<?php
require __DIR__ . '/vendor/autoload.php';
use Revolution\Voicevox\Core\Enums\AccelerationMode;
use Revolution\Voicevox\Core\Onnxruntime;
use Revolution\Voicevox\Core\OpenJtalk;
use Revolution\Voicevox\Core\Synthesizer;
use Revolution\Voicevox\Core\VoiceModelFile;
// Cambia las rutas según dónde tengas instalado voicevox_core
$voicevoxCoreDir = getenv('HOME') . '/.local/voicevox_core';
$onnxruntimeFilename = $voicevoxCoreDir . '/onnxruntime/lib/' . Onnxruntime::libVersionedFilename();
$dictDir = $voicevoxCoreDir . '/dict/open_jtalk_dic_utf_8-1.11';
$vvmPath = $voicevoxCoreDir . '/models/vvms/0.vvm';
// Texto a sintetizar y style ID
$text = 'この音声は、ボイスボックスを使用して、出力されています。';
$styleId = 0;
$outPath = './output.wav';
// Inicialización
$onnxruntime = Onnxruntime::loadOnce($onnxruntimeFilename);
$openJtalk = new OpenJtalk($dictDir);
$synthesizer = new Synthesizer($onnxruntime, $openJtalk, AccelerationMode::Auto);
// Carga el modelo de voz
$model = VoiceModelFile::open($vvmPath);
$synthesizer->loadVoiceModel($model);
// Síntesis de voz
$audioQuery = $synthesizer->createAudioQuery($text, $styleId);
$wav = $synthesizer->synthesis($audioQuery, $styleId);
file_put_contents($outPath, $wav);
echo 'Wrote ' . $outPath . PHP_EOL;
Ejecución:
Síntesis de voz en un solo paso (método tts)
Si quieres saltarte los 2 pasos de createAudioQuery + synthesis, puedes usar el método tts():
$wav = $synthesizer->tts($text, $styleId);
file_put_contents('./output.wav', $wav);
Síntesis de voz con notación katakana
También puedes sintetizar desde notación katakana estilo AquesTalk:
// Uso de ttsFromKana
$wav = $synthesizer->ttsFromKana("コノオンセイワ'、ボイスボックスオ'/シヨーシテ'、シュツリョクサレテイマ'ス。", $styleId);
file_put_contents('./output.wav', $wav);
Uso del diccionario de usuario
Para registrar la lectura de palabras personalizadas se usa UserDict:
use Revolution\Voicevox\Core\UserDict;
use Revolution\Voicevox\Core\Enums\UserDictWordType;
$userDict = new UserDict();
$uuid = $userDict->addWord(
surface: 'ボイボ',
pronunciation: 'ボイボ',
accentType: 0,
wordType: UserDictWordType::ProperNoun,
priority: 10,
);
// Guarda el diccionario
$userDict->save('./mydict.json');
// Aplica el diccionario a OpenJTalk
$openJtalk->useUserDict($userDict);
Ajuste del AudioQuery
Si ajustas el JSON que obtienes con createAudioQuery antes de sintetizar, puedes controlar con detalle la entonación, el tempo, etc.:
$audioQueryJson = $synthesizer->createAudioQuery($text, $styleId);
// Decodifica el JSON y ajústalo
$audioQuery = json_decode($audioQueryJson, true);
$audioQuery['speedScale'] = 1.2; // Velocidad ×1,2
$audioQuery['pitchScale'] = 0.05; // Sube ligeramente el pitch
$wav = $synthesizer->synthesis(json_encode($audioQuery), $styleId);
file_put_contents('./output.wav', $wav);
Obtener frases acentuadas
Puedes obtener la información de las frases acentuadas del texto para revisarla y editarla:
$accentPhrasesJson = $synthesizer->createAccentPhrases($text, $styleId);
$accentPhrases = json_decode($accentPhrasesJson, true);
// Sobrescribe la pitch de las moras y la longitud de fonemas con otro estilo
$updatedJson = $synthesizer->replaceMoraData($accentPhrasesJson, $styleId);
Uso del modo GPU
En entornos con GPU disponible, indicar AccelerationMode::Gpu acelera el procesamiento:
use Revolution\Voicevox\Core\Enums\AccelerationMode;
$synthesizer = new Synthesizer($onnxruntime, $openJtalk, AccelerationMode::Gpu);
// Comprueba si está en modo GPU
if ($synthesizer->isGpuMode()) {
echo 'Ejecutando en modo GPU' . PHP_EOL;
}
Uso de varios modelos de voz
Cargando varios archivos .vvm y cambiando el style ID, puedes alternar entre distintas voces de personajes:
$model0 = VoiceModelFile::open($voicevoxCoreDir . '/models/vvms/0.vvm');
$model1 = VoiceModelFile::open($voicevoxCoreDir . '/models/vvms/1.vvm');
$synthesizer->loadVoiceModel($model0);
$synthesizer->loadVoiceModel($model1);
// Consulta la información de los speakers incluidos en el modelo
$metas = json_decode($synthesizer->metas(), true);
// Descarga un modelo (cuando ya no lo necesites)
$synthesizer->unloadVoiceModel($model0->id());