Python
from magic_hour import Client
from os import getenv
client = Client(token=getenv("MAGIC_HOUR_API_KEY"))
res = client.v1.ai_talking_photo.generate(
assets={
"audio_file_path": "/path/to/1234.mp3",
"image_file_path": "/path/to/1234.png",
},
end_seconds=5.0,
start_seconds=0.0,
name="Talking Photo image",
wait_for_completion=True,
download_outputs=True,
download_directory="."
)import { Client } from "magic-hour";
const client = new Client({ token: process.env["MAGIC_HOUR_API_KEY"] });
const res = await client.v1.aiTalkingPhoto.generate(
{
assets: {
audioFilePath: "/path/to/1234.mp3",
imageFilePath: "/path/to/1234.png",
},
endSeconds: 5.0,
name: "Talking Photo image",
startSeconds: 0.0,
},
{
waitForCompletion: true,
downloadOutputs: true,
downloadDirectory: ".",
},
);package main
import (
os "os"
sdk "github.com/magichourhq/magic-hour-go/client"
nullable "github.com/magichourhq/magic-hour-go/nullable"
ai_talking_photo "github.com/magichourhq/magic-hour-go/resources/v1/ai_talking_photo"
types "github.com/magichourhq/magic-hour-go/types"
)
func main() {
client := sdk.NewClient(
sdk.WithBearerAuth(os.Getenv("MAGIC_HOUR_API_KEY")),
)
res, err := client.V1.AiTalkingPhoto.Create(ai_talking_photo.CreateRequest{
Assets: types.V1AiTalkingPhotoCreateBodyAssets{
AudioFilePath: "api-assets/id/1234.mp3",
ImageFilePath: "api-assets/id/1234.png",
},
EndSeconds: 5.0,
Name: nullable.NewValue("My Talking Photo video"),
Resolution: nullable.NewValue(types.V1AiTalkingPhotoCreateBodyResolutionEnum480p),
StartSeconds: 0.0,
})
}let client = magic_hour::Client::default()
.with_bearer_auth(&std::env::var("MAGIC_HOUR_API_KEY").unwrap());
let res = client
.v1()
.ai_talking_photo()
.create(magic_hour::resources::v1::ai_talking_photo::CreateRequest {
assets: magic_hour::models::V1AiTalkingPhotoCreateBodyAssets {
audio_file_path: "api-assets/id/1234.mp3".to_string(),
image_file_path: "api-assets/id/1234.png".to_string(),
},
end_seconds: 5.0,
name: Some("My Talking Photo video".to_string()),
resolution: Some(
magic_hour::models::V1AiTalkingPhotoCreateBodyResolutionEnum::Enum480p,
),
start_seconds: 0.0,
..Default::default()
})
.await;curl --request POST \
--url https://api.magichour.ai/v1/ai-talking-photo \
--header 'accept: application/json' \
--header "authorization: Bearer $MAGIC_HOUR_API_KEY" \
--header 'content-type: application/json' \
--data '
{
"name": "My Talking Photo video",
"start_seconds": 0,
"end_seconds": 5,
"assets": {
"image_file_path": "api-assets/id/1234.png",
"audio_file_path": "api-assets/id/1234.mp3"
},
"style": {
"generation_mode": "realistic",
"prompt": "A person smiling and speaking naturally to the camera"
},
"resolution": "480p"
}
'<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.magichour.ai/v1/ai-talking-photo",
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([
'name' => 'My Talking Photo video',
'start_seconds' => 0,
'end_seconds' => 5,
'assets' => [
'image_file_path' => 'api-assets/id/1234.png',
'audio_file_path' => 'api-assets/id/1234.mp3'
],
'style' => [
'generation_mode' => 'realistic',
'prompt' => 'A person smiling and speaking naturally to the camera'
],
'resolution' => '480p'
]),
CURLOPT_HTTPHEADER => [
"accept: application/json",
"authorization: Bearer <token>",
"content-type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}HttpResponse<String> response = Unirest.post("https://api.magichour.ai/v1/ai-talking-photo")
.header("accept", "application/json")
.header("content-type", "application/json")
.header("authorization", "Bearer <token>")
.body("{\"name\":\"My Talking Photo video\",\"start_seconds\":0,\"end_seconds\":5,\"assets\":{\"image_file_path\":\"api-assets/id/1234.png\",\"audio_file_path\":\"api-assets/id/1234.mp3\"},\"style\":{\"generation_mode\":\"realistic\",\"prompt\":\"A person smiling and speaking naturally to the camera\"},\"resolution\":\"480p\"}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.magichour.ai/v1/ai-talking-photo")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"start_seconds\": 0,\n \"end_seconds\": 5,\n \"assets\": {\n \"image_file_path\": \"api-assets/id/1234.png\",\n \"audio_file_path\": \"api-assets/id/1234.mp3\"\n },\n \"name\": \"My Talking Photo video\",\n \"style\": {\n \"generation_mode\": \"realistic\",\n \"prompt\": \"A person smiling and speaking naturally to the camera\"\n },\n \"resolution\": \"480p\"\n}"
response = http.request(request)
puts response.read_body{
"id": "cuid-example",
"credits_charged": 450
}{
"code": "invalid_request",
"message": "<string>"
}{
"code": "unauthorized",
"message": "<string>"
}{
"code": "insufficient_credits",
"message": "<string>"
}{
"code": "not_found",
"message": "<string>"
}{
"code": "unprocessable_entity",
"message": "<string>"
}{
"code": "internal_server_error",
"message": "<string>"
}Video Projects
AI Talking Photo API Reference - Magic Hour Docs
Create a talking photo video from an image and an audio file.
POST
/
v1
/
ai-talking-photo
Python
from magic_hour import Client
from os import getenv
client = Client(token=getenv("MAGIC_HOUR_API_KEY"))
res = client.v1.ai_talking_photo.generate(
assets={
"audio_file_path": "/path/to/1234.mp3",
"image_file_path": "/path/to/1234.png",
},
end_seconds=5.0,
start_seconds=0.0,
name="Talking Photo image",
wait_for_completion=True,
download_outputs=True,
download_directory="."
)import { Client } from "magic-hour";
const client = new Client({ token: process.env["MAGIC_HOUR_API_KEY"] });
const res = await client.v1.aiTalkingPhoto.generate(
{
assets: {
audioFilePath: "/path/to/1234.mp3",
imageFilePath: "/path/to/1234.png",
},
endSeconds: 5.0,
name: "Talking Photo image",
startSeconds: 0.0,
},
{
waitForCompletion: true,
downloadOutputs: true,
downloadDirectory: ".",
},
);package main
import (
os "os"
sdk "github.com/magichourhq/magic-hour-go/client"
nullable "github.com/magichourhq/magic-hour-go/nullable"
ai_talking_photo "github.com/magichourhq/magic-hour-go/resources/v1/ai_talking_photo"
types "github.com/magichourhq/magic-hour-go/types"
)
func main() {
client := sdk.NewClient(
sdk.WithBearerAuth(os.Getenv("MAGIC_HOUR_API_KEY")),
)
res, err := client.V1.AiTalkingPhoto.Create(ai_talking_photo.CreateRequest{
Assets: types.V1AiTalkingPhotoCreateBodyAssets{
AudioFilePath: "api-assets/id/1234.mp3",
ImageFilePath: "api-assets/id/1234.png",
},
EndSeconds: 5.0,
Name: nullable.NewValue("My Talking Photo video"),
Resolution: nullable.NewValue(types.V1AiTalkingPhotoCreateBodyResolutionEnum480p),
StartSeconds: 0.0,
})
}let client = magic_hour::Client::default()
.with_bearer_auth(&std::env::var("MAGIC_HOUR_API_KEY").unwrap());
let res = client
.v1()
.ai_talking_photo()
.create(magic_hour::resources::v1::ai_talking_photo::CreateRequest {
assets: magic_hour::models::V1AiTalkingPhotoCreateBodyAssets {
audio_file_path: "api-assets/id/1234.mp3".to_string(),
image_file_path: "api-assets/id/1234.png".to_string(),
},
end_seconds: 5.0,
name: Some("My Talking Photo video".to_string()),
resolution: Some(
magic_hour::models::V1AiTalkingPhotoCreateBodyResolutionEnum::Enum480p,
),
start_seconds: 0.0,
..Default::default()
})
.await;curl --request POST \
--url https://api.magichour.ai/v1/ai-talking-photo \
--header 'accept: application/json' \
--header "authorization: Bearer $MAGIC_HOUR_API_KEY" \
--header 'content-type: application/json' \
--data '
{
"name": "My Talking Photo video",
"start_seconds": 0,
"end_seconds": 5,
"assets": {
"image_file_path": "api-assets/id/1234.png",
"audio_file_path": "api-assets/id/1234.mp3"
},
"style": {
"generation_mode": "realistic",
"prompt": "A person smiling and speaking naturally to the camera"
},
"resolution": "480p"
}
'<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.magichour.ai/v1/ai-talking-photo",
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([
'name' => 'My Talking Photo video',
'start_seconds' => 0,
'end_seconds' => 5,
'assets' => [
'image_file_path' => 'api-assets/id/1234.png',
'audio_file_path' => 'api-assets/id/1234.mp3'
],
'style' => [
'generation_mode' => 'realistic',
'prompt' => 'A person smiling and speaking naturally to the camera'
],
'resolution' => '480p'
]),
CURLOPT_HTTPHEADER => [
"accept: application/json",
"authorization: Bearer <token>",
"content-type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}HttpResponse<String> response = Unirest.post("https://api.magichour.ai/v1/ai-talking-photo")
.header("accept", "application/json")
.header("content-type", "application/json")
.header("authorization", "Bearer <token>")
.body("{\"name\":\"My Talking Photo video\",\"start_seconds\":0,\"end_seconds\":5,\"assets\":{\"image_file_path\":\"api-assets/id/1234.png\",\"audio_file_path\":\"api-assets/id/1234.mp3\"},\"style\":{\"generation_mode\":\"realistic\",\"prompt\":\"A person smiling and speaking naturally to the camera\"},\"resolution\":\"480p\"}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.magichour.ai/v1/ai-talking-photo")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"start_seconds\": 0,\n \"end_seconds\": 5,\n \"assets\": {\n \"image_file_path\": \"api-assets/id/1234.png\",\n \"audio_file_path\": \"api-assets/id/1234.mp3\"\n },\n \"name\": \"My Talking Photo video\",\n \"style\": {\n \"generation_mode\": \"realistic\",\n \"prompt\": \"A person smiling and speaking naturally to the camera\"\n },\n \"resolution\": \"480p\"\n}"
response = http.request(request)
puts response.read_body{
"id": "cuid-example",
"credits_charged": 450
}{
"code": "invalid_request",
"message": "<string>"
}{
"code": "unauthorized",
"message": "<string>"
}{
"code": "insufficient_credits",
"message": "<string>"
}{
"code": "not_found",
"message": "<string>"
}{
"code": "unprocessable_entity",
"message": "<string>"
}{
"code": "internal_server_error",
"message": "<string>"
}Authorizations
Bearer authentication header of the form Bearer <api_key>, where <api_key> is your API key. To get your API key, go to Developer Hub and click "Create new API Key".
Body
application/json
Body
Provide the assets for creating a talking photo
Response
Success
Success
Unique ID of the video. Use it with the Get video Project API to fetch status and downloads.
Example:
"cuid-example"
The amount of credits deducted from your account to generate the video. If the status is not 'complete', this value is an estimate and may be adjusted upon completion based on the actual FPS of the output video.
If video generation fails, credits will be refunded, and this field will be updated to include the refund.
Example:
450
Was this page helpful?