File size: 6,388 Bytes
122b90e
 
 
 
 
 
 
 
 
 
 
 
468dbfa
0ef4926
122b90e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f339966
122b90e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
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()