TayyabTanveer's picture
Update app.py
0ef4926 verified
import streamlit as st
import requests
import time
# API Endpoints
GENERATE_VIDEO_URL = "https://api.heygen.com/v2/video/generate"
VIDEO_STATUS_URL = "https://api.heygen.com/v1/video_status.get"
# API Headers
HEADERS = {
"accept": "application/json",
"content-type": "application/json",
"x-api-key": "MWE1NDAyOWU1ZDkyNDhlZmIzM2MzYzY3ZmU1MGNiZDQtMTc0NDAxMjI0MA==" # Replace with actual API key
}
# Streamlit UI
st.title("HeyGen Video Generator 🎬")
# instructions for users
st.subheader("Follow these simple steps:")
st.caption("""1️⃣ Enter Video Details – Provide a title.\n
2️⃣ Add Scenes – Click "βž• Add Scene" to add multiple scenes, each with:\n
Avatar ID & Style\n
Voice ID & Script Input\n
Emotion & Positioning\n
3️⃣ Generate Video – Click "πŸš€ Generate Video" to start processing.\n
4️⃣ Track Progress – The app will automatically check the status every half minute.\n
5️⃣ Watch & Reset – Once the video is ready, it will be displayed. Click "πŸ”„ Reset All" to start over.\n\n""")
# Session state to track scenes and video status
if "scenes" not in st.session_state:
st.session_state.scenes = [] # List to hold scene data
if "video_id" not in st.session_state:
st.session_state.video_id = None
if "video_status" not in st.session_state:
st.session_state.video_status = None
# Function to reset all inputs
def reset_all():
st.session_state.scenes = []
st.session_state.video_id = None
st.session_state.video_status = None
st.rerun()
# Button to add a new scene
if st.button("βž• Add Scene",type="primary"):
st.session_state.scenes.append({
"avatar_id": "",
"avatar_style": "normal",
"offset_x": 0,
"offset_y": 0,
"voice_id": "",
"input_text": "",
"emotion": "Friendly"
})
# Input fields for video title and callback ID
title = st.text_input("Title", placeholder="Enter video title")
# Render scenes dynamically
for i, scene in enumerate(st.session_state.scenes):
st.subheader(f"🎬 Scene {i+1}")
# Inputs for each scene
scene["avatar_id"] = st.text_input(f"Avatar ID (Scene {i+1})", scene["avatar_id"], key=f"avatar_id_{i}")
scene["avatar_style"] = st.selectbox(f"Avatar Style (Scene {i+1})", ["normal", "circle", "closeUp"], index=0, key=f"avatar_style_{i}")
scene["offset_x"] = st.number_input(f"Offset X (Scene {i+1})", value=scene["offset_x"], key=f"offset_x_{i}")
scene["offset_y"] = st.number_input(f"Offset Y (Scene {i+1})", value=scene["offset_y"], key=f"offset_y_{i}")
scene["voice_id"] = st.text_input(f"Voice ID (Scene {i+1})", scene["voice_id"], key=f"voice_id_{i}")
scene["input_script"] = st.text_area(f"Input script (Scene {i+1})", scene["input_text"], key=f"input_text_{i}")
scene["emotion"] = st.selectbox(f"Voice emotion (Scene {i+1})", ["Friendly", "Serious", "Excited", "Soothing", "Broadcaster"], index=0, key=f"emotion_{i}")
# Button to generate video
if st.button("πŸš€ Generate Video"):
if not title or not st.session_state.scenes:
st.error("❌ Please fill in all required fields and add at least one scene!")
else:
# Constructing video_inputs array from scenes
video_inputs = [
{
"character": {
"type": "avatar",
"avatar_id": scene["avatar_id"],
"scale": 1,
"avatar_style": scene["avatar_style"],
"offset": {"x": scene["offset_x"], "y": scene["offset_y"]},
},
"voice": {
"type": "text",
"voice_id": scene["voice_id"],
"input_text": scene["input_script"],
"speed": 1,
"emotion": scene["emotion"],
},
}
for scene in st.session_state.scenes
]
# API Request Payload
payload = {
"caption": False,
"title": title,
"dimension": {"width": 1280, "height": 720},
"video_inputs": video_inputs,
}
# Call API to generate video
response = requests.post(GENERATE_VIDEO_URL, json=payload, headers=HEADERS)
# Handle API Response
if response.status_code == 200:
data = response.json()
if data.get("error") is None:
st.session_state.video_id = data["data"]["video_id"]
st.success(f"βœ… Video generation started! Video ID: {st.session_state.video_id}")
else:
st.error(f"❌ API Error: {data['error']}")
else:
st.error(f"❌ Request Failed! Status Code: {response.status_code}")
# Function to check video status
def check_video_status(video_id):
while True:
params = {"video_id": video_id}
response = requests.get(VIDEO_STATUS_URL, headers=HEADERS, params=params)
if response.status_code == 200:
data = response.json()
status = data["data"]["status"]
st.session_state.video_status = status
# Show status messages
if status in ["processing", "waiting", "pending"]:
st.info(f"⏳ Video is still {status}. Please wait...")
elif status == "failed":
error_info = data["data"].get("error", {})
error_message = error_info.get("message", "An unknown error occurred.")
st.error(f"❌ Video generation failed: {error_message}")
return
elif status == "completed":
video_url = data["data"].get("video_url")
if video_url:
st.success("πŸŽ‰ Video is ready! Watch it below:")
st.video(video_url)
else:
st.warning("⚠️ Video completed but URL is missing.")
return
else:
st.error(f"❌ Request Failed! Status Code: {response.status_code}")
return
time.sleep(30) # Wait 1 minute before checking again
# Check video status if video ID is available
if st.session_state.video_id:
check_video_status(st.session_state.video_id)
# Reset button (only shows after video generation)
if st.session_state.video_status == "completed":
if st.button("πŸ”„ Reset All"):
reset_all()