Installation
composer require google/cloud-text-to-speech
Add the package to config/app.php under providers if using Laravel's service container.
Authentication Configure credentials via:
GOOGLE_APPLICATION_CREDENTIALS pointing to a service account JSON key file)..env:
GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
First Use Case: Synthesize Speech
use Google\Cloud\TextToSpeech\V1\TextToSpeechClient;
use Google\Cloud\TextToSpeech\V1\SynthesizeSpeechRequest;
$client = new TextToSpeechClient();
$response = $client->synthesizeSpeech(
new SynthesizeSpeechRequest([
'input' => ['text' => 'Hello, world!'],
'voice' => ['languageCode' => 'en-US', 'name' => 'en-US-Wavenet-D'],
'audioConfig' => ['audioEncoding' => 'MP3'],
])
);
file_put_contents('output.mp3', $response->getAudioContent());
TextToSpeechClient: Main client class for all operations.SynthesizeSpeechRequest: Core request builder for speech synthesis.ListVoicesRequest: Fetch available voices/languages.SSML Support: Use <speak> tags for advanced formatting (e.g., <prosody rate="1.5">).Voice Selection List available voices and filter by language/code:
$voices = $client->listVoices(new ListVoicesRequest(['languageCode' => 'es-ES']));
foreach ($voices->getVoices() as $voice) {
log($voice->getName()); // e.g., 'es-ES-Wavenet-A'
}
Batch Processing
Use SynthesizeSpeechRequest with input as an array for multiple texts:
$request = new SynthesizeSpeechRequest([
'input' => ['texts' => ['Hello', 'World']],
'voice' => ['name' => 'en-US-Studio-O'],
'audioConfig' => ['audioEncoding' => 'LINEAR16'],
]);
SSML Integration Pass SSML directly for dynamic formatting:
$ssml = '<speak><prosody rate="slow">Hello</prosody><break time="1s"/><prosody rate="fast">World</prosody></speak>';
$response = $client->synthesizeSpeech([
'input' => ['ssml' => $ssml],
'voice' => ['languageCode' => 'en-US'],
'audioConfig' => ['audioEncoding' => 'MP3'],
]);
Streaming Responses For large audio, stream chunks to disk:
$response = $client->synthesizeSpeech($request);
$handle = fopen('large_output.mp3', 'wb');
fwrite($handle, $response->getAudioContent());
fclose($handle);
Service Provider Bind the client to Laravel's container for dependency injection:
// app/Providers/AppServiceProvider.php
public function register()
{
$this->app->singleton(TextToSpeechClient::class, function () {
return new TextToSpeechClient();
});
}
Configurable Voices
Store voice preferences in config/text-to-speech.php:
return [
'default_voice' => 'en-US-Wavenet-D',
'supported_languages' => ['en-US', 'es-ES'],
];
Access via config('text-to-speech.default_voice').
Jobs for Async Processing Offload synthesis to a queue job:
// app/Jobs/SynthesizeSpeechJob.php
public function handle()
{
$client = resolve(TextToSpeechClient::class);
$response = $client->synthesizeSpeech($this->request);
Storage::disk('s3')->put('audio.mp3', $response->getAudioContent());
}
Authentication Failures
Google\Auth\Exception\GoogleAuthException.GOOGLE_APPLICATION_CREDENTIALS points to a valid service account JSON file with text-to-speech enabled in Google Cloud Console.GOOGLE_CLOUD_PROJECT env var to explicitly set the project ID.Quota Limits
$client->getOperationsClient()->listOperations($client->getName());
Audio Encoding Mismatches
OGG_OPUS) throw ApiException.MP3, LINEAR16, MULAW, AMR, AMR_WB, OPUS.SSML Validation
INVALID_ARGUMENT.Enable API Logging
Set the GOOGLE_CLOUD_DEBUG environment variable to true for verbose logs:
GOOGLE_CLOUD_DEBUG=true
Inspect Requests
Use Google\ApiCore\ApiException::getStatus() to check HTTP status codes:
try {
$response = $client->synthesizeSpeech($request);
} catch (ApiException $e) {
log($e->getStatus()->getCode()); // e.g., 403 for PERMISSION_DENIED
}
Custom Voice Profiles
Extend SynthesizeSpeechRequest for project-specific voice configurations:
class CustomSynthesizeRequest extends SynthesizeSpeechRequest {
public function __construct(array $options = []) {
$options['voice'] = array_merge($options['voice'] ?? [], [
'name' => config('text-to-speech.default_voice'),
]);
parent::__construct($options);
}
}
Middleware for Requests Add preprocessing/validation via Laravel middleware:
// app/Http/Middleware/SynthesizeSpeechMiddleware.php
public function handle($request, Closure $next) {
$request->merge([
'audioConfig' => ['audioEncoding' => 'MP3'],
]);
return $next($request);
}
Local Fallback Cache responses locally and serve stale audio during outages:
$cacheKey = md5($request->getInput()->getText());
$audio = Cache::get($cacheKey);
if (!$audio) {
$response = $client->synthesizeSpeech($request);
$audio = $response->getAudioContent();
Cache::put($cacheKey, $audio, now()->addHours(1));
}
TextToSpeechClient once (e.g., as a singleton) to reuse HTTP connections.SynthesizeSpeechRequest to reduce API calls.LINEAR16 to MP3 in-memory to reduce storage:
use FFMpeg\FFMpeg;
$ffmpeg = FFMpeg::create();
$video = $ffmpeg->open('audio.raw');
$video->save('audio.mp3');
How can I help you explore Laravel packages today?