import requests import json from moviepy.editor import VideoFileClip import os API_KEY = "YTBjYzk5MjI1ZWQzNGViOTgxMTI0NjM2OGQ5NDc2OGEtMTczMzk5MjA5MA==" AUDIO_URL = "https://drive.google.com/file/d/1CF8TjWwPWiIPJX3D1bjpMopinHt4iw1D/view?usp=sharing" # API ENDPOINTS #GET VIDEO_GENERATION_STATUS = "https://api.heygen.com/v1/video_status.get" LIST_TALKING_PHOTOS = "https://api.heygen.com/v1/talking_photo.list" #POST VIDEO_GENERATION = "https://api.heygen.com/v2/video/generate" UPLOAD_PHOTO = "https://upload.heygen.com/v1/talking_photo" def video_generation_payload(title, avatar_id, audio_url): return { "title": title, "caption": False, # "callback_id": "callback_id", "dimension": { "width": 720, "height": 1280 }, "video_inputs": [ { "character": { "type": "avatar", "avatar_id": avatar_id, "scale": 1.0, "avatar_style": "normal", "offset": { "x": 0.0, "y": 0.0 }, "matting": False }, "voice": { "type": "audio", "audio_url": audio_url }, } ], # "callback_url": "callback_url" } def talking_photo_payload(title, talking_photo_id, audio_url): print(f"Creating video with title: {title}, talking_photo_id: {talking_photo_id}, audio_url: {audio_url}") return { "title": title, "caption": False, # "callback_id": "callback_id", "dimension": { "width": 720, "height": 1280 }, "video_inputs": [ { "character": { "type": "talking_photo", "talking_photo_id": talking_photo_id }, "voice": { "type": "audio", "audio_url": audio_url }, "talking_style": "stable", "expression": "happy", } ], # "callback_url": "callback_url" } def upload_photo(file_path, type): print(f"Uploading photo {file_path}") with open(file_path, "rb") as f: resp = requests.post(UPLOAD_PHOTO, data=f, headers={"Content-Type": type, "x-api-key": API_KEY}).json() try: talking_photo_id = resp["data"]["talking_photo_id"] return talking_photo_id except Exception as e: print(f"Error uploading photo: {e}") return resp def list_talking_photos(): print("Listing talking photos") headers = { "accept": "application/json", "x-api-key": API_KEY } response = requests.get(LIST_TALKING_PHOTOS, headers=headers).json() return response def download_video(video_id, video_url): download_video = requests.get(video_url) print(f"Downloading video {video_id}") with open(f"{video_id}.mp4", "wb") as f: f.write(download_video.content) def create_video(title, avatar_id, audio_url): print(f"Creating video with title: {title}, avatar_id: {avatar_id}, audio_url: {audio_url}") headers = { "accept": "application/json", "content-type": "application/json", "x-api-key": API_KEY } payload = talking_photo_payload(title, avatar_id, audio_url) response = requests.post(VIDEO_GENERATION, json=payload, headers=headers).json() try: video_id = response["data"]["video_id"] print(f"Video ID: {video_id}") return video_id except Exception as e: print(f"Error creating video: {e}") return response def get_video_status(video_id): headers = { "accept": "application/json", "x-api-key": API_KEY } response = requests.get(VIDEO_GENERATION_STATUS, headers=headers, params={"video_id": video_id}).json() print(f"Video status: {response['data']['status']}") return { "id": response["data"]["id"], "status": response["data"]["status"], "video_url": response["data"]["video_url"], "thumbnail_url": response["data"]["thumbnail_url"] } def split_video(video_id): print(f"Splitting video {video_id}.mp4") with open("clips_metadata.json", "r") as f: clips_metadata = json.load(f) video = VideoFileClip(f"{video_id}.mp4") clips = [] for clip_data in clips_metadata: start_time = clip_data["start_time_ms"] end_time = clip_data["end_time_ms"] # convert milliseconds to seconds start_time /= 1000 end_time /= 1000 try: clip_name = clip_data["file_name"].split(".")[0]+".mp4" clip = video.subclip(start_time, end_time) clips.append(clip) except Exception as e: print(f"Error in clip {clip_name}: {e}") clips_dir = f"{video_id}_clips" os.makedirs(clips_dir, exist_ok=True) print(f"Saving clips to {clips_dir}") for i, clip in enumerate(clips): clip_path = os.path.join(clips_dir, clips_metadata[i]["file_name"].split(".")[0]+".mp4") clip.write_videofile(clip_path, codec="libx264", audio_codec="aac")