curl --request POST \
--url https://api.goenhance.ai/api/v1/videos/generations \
--header 'Content-Type: application/json' \
--data '
{
"model": "ai-talking-avatar",
"image_url": "https://example.com/portrait.png",
"audio_url": "https://example.com/speech.mp3",
"prompt": "a woman speaking calmly to the camera",
"resolution": "720p"
}
'import requests
url = "https://api.goenhance.ai/api/v1/videos/generations"
payload = {
"model": "ai-talking-avatar",
"image_url": "https://example.com/portrait.png",
"audio_url": "https://example.com/speech.mp3",
"prompt": "a woman speaking calmly to the camera",
"resolution": "720p"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
model: 'ai-talking-avatar',
image_url: 'https://example.com/portrait.png',
audio_url: 'https://example.com/speech.mp3',
prompt: 'a woman speaking calmly to the camera',
resolution: '720p'
})
};
fetch('https://api.goenhance.ai/api/v1/videos/generations', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.goenhance.ai/api/v1/videos/generations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => 'ai-talking-avatar',
'image_url' => 'https://example.com/portrait.png',
'audio_url' => 'https://example.com/speech.mp3',
'prompt' => 'a woman speaking calmly to the camera',
'resolution' => '720p'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.goenhance.ai/api/v1/videos/generations"
payload := strings.NewReader("{\n \"model\": \"ai-talking-avatar\",\n \"image_url\": \"https://example.com/portrait.png\",\n \"audio_url\": \"https://example.com/speech.mp3\",\n \"prompt\": \"a woman speaking calmly to the camera\",\n \"resolution\": \"720p\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.goenhance.ai/api/v1/videos/generations")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"ai-talking-avatar\",\n \"image_url\": \"https://example.com/portrait.png\",\n \"audio_url\": \"https://example.com/speech.mp3\",\n \"prompt\": \"a woman speaking calmly to the camera\",\n \"resolution\": \"720p\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.goenhance.ai/api/v1/videos/generations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"ai-talking-avatar\",\n \"image_url\": \"https://example.com/portrait.png\",\n \"audio_url\": \"https://example.com/speech.mp3\",\n \"prompt\": \"a woman speaking calmly to the camera\",\n \"resolution\": \"720p\"\n}"
response = http.request(request)
puts response.read_body{
"code": 0,
"msg": "Success",
"data": {
"img_uuid": "c12b656c-747a-44fd-9c80-add79b0c52d5",
"cost": 5.82
}
}AI Talking Avatar
AI Talking Avatar. How it works — one portrait image plus one audio track: the person in the image speaks the audio, lip-synced.
Output length — by default the video is as long as your audio. Before any tokens are deducted, GoEnhance transfers audio_url to its own storage and measures the real duration — that measurement is what you are billed for, and it is also what enforces the 3-60s limit. Because the file is measured and then sent onward from GoEnhance’s storage, swapping the URL afterwards has no effect.
To make a shorter video, set the optional duration (whole seconds, 3-60): only the first duration seconds of the audio are used, and you are billed for duration seconds. It cannot exceed the audio length. With duration set, the audio itself may be longer than 60 seconds.
Audio requirements — 3-60 seconds (or at least duration seconds when duration is set), up to 50MB. Clear speech with little background noise gives the best lip sync.
Portrait requirements — up to 10MB. The face must be clearly visible, unobstructed and roughly front-facing.
Pricing — per second of output (the audio length, or duration when set), in tokens (USD at $0.02/token):
| resolution | tokens/s | USD/s |
|---|---|---|
| 540p | 0.5 | $0.01 |
| 720p | 1 | $0.02 |
A 30-second clip therefore costs 15 tokens at 540p (= 0.30).At720pthesameclipcosts30tokens(=0.60).
Returns an img_uuid; poll GET /api/v1/jobs/detail (or use custom_callback_url) to get the generated video.
curl --request POST \
--url https://api.goenhance.ai/api/v1/videos/generations \
--header 'Content-Type: application/json' \
--data '
{
"model": "ai-talking-avatar",
"image_url": "https://example.com/portrait.png",
"audio_url": "https://example.com/speech.mp3",
"prompt": "a woman speaking calmly to the camera",
"resolution": "720p"
}
'import requests
url = "https://api.goenhance.ai/api/v1/videos/generations"
payload = {
"model": "ai-talking-avatar",
"image_url": "https://example.com/portrait.png",
"audio_url": "https://example.com/speech.mp3",
"prompt": "a woman speaking calmly to the camera",
"resolution": "720p"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
model: 'ai-talking-avatar',
image_url: 'https://example.com/portrait.png',
audio_url: 'https://example.com/speech.mp3',
prompt: 'a woman speaking calmly to the camera',
resolution: '720p'
})
};
fetch('https://api.goenhance.ai/api/v1/videos/generations', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.goenhance.ai/api/v1/videos/generations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => 'ai-talking-avatar',
'image_url' => 'https://example.com/portrait.png',
'audio_url' => 'https://example.com/speech.mp3',
'prompt' => 'a woman speaking calmly to the camera',
'resolution' => '720p'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.goenhance.ai/api/v1/videos/generations"
payload := strings.NewReader("{\n \"model\": \"ai-talking-avatar\",\n \"image_url\": \"https://example.com/portrait.png\",\n \"audio_url\": \"https://example.com/speech.mp3\",\n \"prompt\": \"a woman speaking calmly to the camera\",\n \"resolution\": \"720p\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.goenhance.ai/api/v1/videos/generations")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"ai-talking-avatar\",\n \"image_url\": \"https://example.com/portrait.png\",\n \"audio_url\": \"https://example.com/speech.mp3\",\n \"prompt\": \"a woman speaking calmly to the camera\",\n \"resolution\": \"720p\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.goenhance.ai/api/v1/videos/generations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"ai-talking-avatar\",\n \"image_url\": \"https://example.com/portrait.png\",\n \"audio_url\": \"https://example.com/speech.mp3\",\n \"prompt\": \"a woman speaking calmly to the camera\",\n \"resolution\": \"720p\"\n}"
response = http.request(request)
puts response.read_body{
"code": 0,
"msg": "Success",
"data": {
"img_uuid": "c12b656c-747a-44fd-9c80-add79b0c52d5",
"cost": 5.82
}
}Body
Optional. A publicly accessible HTTPS URL. When the task status changes (processing / success / failed), GoEnhance sends a POST request to this URL. The request body is identical to the response of GET /api/v1/jobs/detail. If your server does not respond with HTTP 200, the notification is retried up to 3 times, with a 3-second timeout per attempt.
"https://your-server.com/goenhance/callback"
