hudsonly / ai
Official PHP SDK for the Hudsonly AI API
v0.1.0
2026-02-16 20:30 UTC
Requires
- php: >=8.1
- guzzlehttp/guzzle: ^7.5
Requires (Dev)
- phpunit/phpunit: ^10.0
README
Official PHP SDK for the Hudsonly AI API — Text-to-Speech, Speech-to-Text, Text Embeddings, and Avatar Video Generation.
Installation
composer require hudsonly/sdk
Quick Start
use Hudsonly\HudsonlyAI;
$client = new HudsonlyAI('your-api-token');
// Text to Speech
$result = $client->tts()->generate(['text' => 'Hello world', 'voice' => 'af_heart']);
echo $result->audioUrl;
// Speech to Text
$result = $client->transcription()->generate(['audio' => '/path/to/recording.mp3']);
echo $result->text;
// Text Embeddings
$result = $client->embeddings()->generate(['texts' => ['Hello', 'World']]);
print_r($result->embeddings);
// Avatar Video (auto-polls until complete)
$result = $client->avatar()->generate([
'image' => '/path/to/photo.jpg',
'audio' => '/path/to/speech.mp3',
'model' => 'sadtalker',
]);
echo $result->videoUrl;
Services
Text to Speech
$result = $client->tts()->generate([
'text' => 'Hello world',
'voice' => 'af_heart', // Voice identifier
'format' => 'mp3', // 'mp3' or 'wav'
'speed' => 1.0, // 0.5 to 2.0
]);
echo $result->audioUrl;
echo $result->durationSeconds;
Speech to Text (Transcription)
// From a local file
$result = $client->transcription()->generate([
'audio' => '/path/to/recording.mp3',
'model' => 'base', // 'tiny', 'base', 'small', 'medium'
'language' => 'en', // Optional, auto-detected if omitted
]);
echo $result->text;
foreach ($result->segments as $segment) {
echo "[{$segment->start}s - {$segment->end}s] {$segment->text}\n";
}
// From a URL
$result = $client->transcription()->generate([
'audio_url' => 'https://example.com/audio.mp3',
]);
Text Embeddings
$result = $client->embeddings()->generate(['texts' => ['Hello', 'World']]);
echo $result->dimension; // 1024
echo $result->model; // 'bge-m3'
Avatar Video Generation
// Auto-poll (recommended)
$result = $client->avatar()->generate([
'image' => '/path/to/photo.jpg',
'audio' => '/path/to/speech.mp3',
'model' => 'sadtalker',
'poll_interval' => 5, // Seconds between polls
'timeout' => 600, // Max wait time
]);
echo $result->videoUrl;
// Manual submission
$task = $client->avatar()->create([
'image' => '/path/to/photo.jpg',
'audio' => '/path/to/speech.mp3',
]);
echo $task->id; // Poll via $client->tasks()->get($task->id)
// LivePortrait (video-driven)
$result = $client->avatar()->generate([
'image' => '/path/to/photo.jpg',
'video' => '/path/to/driving_video.mp4',
'model' => 'liveportrait',
]);
Resources
Tasks
$tasks = $client->tasks()->list(['service' => 'avatar', 'status' => 'completed']);
foreach ($tasks->data as $task) {
echo "{$task->id}: {$task->status}\n";
}
$task = $client->tasks()->get('task-uuid');
Credits
$balance = $client->credits()->balance();
echo $balance->balance;
$history = $client->credits()->history(['type' => 'usage', 'per_page' => 50]);
foreach ($history->data as $txn) {
echo "{$txn->amount}: {$txn->description}\n";
}
Other Methods
$services = $client->services();
$limits = $client->rateLimits();
Error Handling
use Hudsonly\Exceptions\AuthenticationException;
use Hudsonly\Exceptions\InsufficientCreditsException;
use Hudsonly\Exceptions\RateLimitException;
use Hudsonly\Exceptions\ValidationException;
use Hudsonly\Exceptions\TaskException;
use Hudsonly\Exceptions\TaskTimeoutException;
try {
$result = $client->tts()->generate(['text' => 'Hello']);
} catch (AuthenticationException $e) {
echo "Invalid API key";
} catch (InsufficientCreditsException $e) {
echo "Not enough credits";
} catch (RateLimitException $e) {
echo "Rate limited, retry after {$e->retryAfter}s";
} catch (ValidationException $e) {
echo "Validation errors: " . print_r($e->errors, true);
}
Requirements
- PHP 8.1+
- Guzzle 7.5+ (installed automatically)
License
MIT