MySafeCode commited on
Commit
3f36bac
·
verified ·
1 Parent(s): 4601cdf

Update a.py

Browse files
Files changed (1) hide show
  1. a.py +163 -69
a.py CHANGED
@@ -2,18 +2,55 @@ import os
2
  import time
3
  import gradio as gr
4
  from byteplussdkarkruntime import Ark
 
 
5
 
6
  # Get API key from Hugging Face secret "Key"
7
  API_KEY = os.environ.get("Key", "")
8
 
9
- # Initialize client exactly like your working code
10
  client = Ark(
11
  base_url="https://ark.ap-southeast.bytepluses.com/api/v3",
12
  api_key=API_KEY,
 
 
13
  )
14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  def generate_video(image_path, prompt_text, progress=gr.Progress()):
16
- """Generate video using HF temp URL trick"""
 
 
 
 
 
 
17
 
18
  if not API_KEY:
19
  yield "❌ API Key not configured. Please add 'Key' secret.", None
@@ -26,8 +63,7 @@ def generate_video(image_path, prompt_text, progress=gr.Progress()):
26
  try:
27
  progress(0, desc="Preparing image...")
28
 
29
- # THE TRICK: image_path is already the file path string
30
- # HF automatically serves it as /file=path
31
  image_url = f"/file={image_path}"
32
  print(f"Using image URL: {image_url}")
33
 
@@ -35,23 +71,30 @@ def generate_video(image_path, prompt_text, progress=gr.Progress()):
35
 
36
  progress(0.2, desc="Creating request...")
37
 
38
- # Exactly your working code structure
39
- print("----- create request -----")
40
- create_result = client.content_generation.tasks.create(
41
- model="seedance-1-5-pro-251215",
42
- content=[
43
- {
44
- "type": "text",
45
- "text": prompt_text
46
- },
47
- {
48
- "type": "image_url",
49
- "image_url": {
50
- "url": image_url # Using HF temp URL!
 
51
  }
52
- }
53
- ]
54
- )
 
 
 
 
 
 
55
 
56
  task_id = create_result.id
57
  print(f"Task created: {task_id}")
@@ -59,68 +102,107 @@ def generate_video(image_path, prompt_text, progress=gr.Progress()):
59
 
60
  progress(0.3, desc="Polling for results...")
61
 
62
- # Polling exactly like your working code
63
  attempts = 0
64
- max_attempts = 120 # 2 minutes max
65
 
66
  while attempts < max_attempts:
67
- get_result = client.content_generation.tasks.get(task_id=task_id)
68
- status = get_result.status
69
-
70
- if status == "succeeded":
71
- progress(1.0, desc="Complete!")
72
- # Extract video URL from the response structure we saw
73
- video_url = get_result.content.video_url if hasattr(get_result, 'content') else None
74
- print(f"Video URL: {video_url}")
75
- yield "✅ Video generated successfully!", video_url
76
- return
77
 
78
- elif status == "failed":
79
- error_msg = get_result.error if hasattr(get_result, 'error') else "Unknown error"
80
- yield f"❌ Failed: {error_msg}", None
81
- return
82
- else:
83
- progress(0.3 + (attempts/max_attempts)*0.7, desc=f"Status: {status}")
84
- yield f"⏳ Status: {status}... (attempt {attempts + 1})", None
85
- time.sleep(1)
 
 
 
 
 
 
 
 
 
 
 
 
86
  attempts += 1
87
 
88
  yield "⏰ Timeout after 2 minutes", None
89
 
90
  except Exception as e:
91
  print(f"Error: {e}")
92
- yield f" Error: {str(e)}", None
 
 
 
 
 
 
 
93
 
94
- # Simple, clean interface
95
  with gr.Blocks(title="BytePlus Video Generator", theme=gr.themes.Soft()) as demo:
96
 
97
  gr.Markdown("""
98
  # 🎥 BytePlus Video Generator
99
-
100
- Upload an image and describe the video you want to generate.
101
  """)
102
 
103
- # Show API key status
104
- if API_KEY:
105
- gr.Markdown("✅ **API Key:** Configured")
106
- else:
107
- gr.Markdown("❌ **API Key:** Not configured - please add 'Key' secret")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
 
109
  with gr.Row():
110
  with gr.Column():
111
- # Image upload - type="filepath" returns a string path
112
  image_input = gr.Image(
113
  label="Upload Starting Image",
114
- type="filepath", # This returns a string path
115
  height=300
116
  )
117
 
118
- # Text prompt
 
 
 
 
 
 
 
119
  prompt = gr.Textbox(
120
- label="Video Description",
121
- lines=4,
122
- placeholder="Describe what you want to see...",
123
- value="At breakneck speed, drones thread through intricate obstacles or stunning natural wonders, delivering an immersive, heart-pounding flying experience. --duration 5 --camerafixed false"
 
 
 
 
 
 
 
124
  )
125
 
126
  # Generate button
@@ -130,7 +212,7 @@ with gr.Blocks(title="BytePlus Video Generator", theme=gr.themes.Soft()) as demo
130
  # Status
131
  status = gr.Textbox(
132
  label="Status",
133
- lines=4,
134
  interactive=False
135
  )
136
 
@@ -140,24 +222,36 @@ with gr.Blocks(title="BytePlus Video Generator", theme=gr.themes.Soft()) as demo
140
  interactive=False
141
  )
142
 
143
- # Example prompts
144
  gr.Markdown("---")
145
- gr.Markdown("### Example Prompts")
146
  with gr.Row():
147
- gr.Button("Nature").click(
148
- fn=lambda: "Aerial drone shot over mountains at sunrise, cinematic --duration 5 --camerafixed false",
149
- outputs=prompt
 
 
 
 
 
 
 
 
 
 
 
 
150
  )
151
- gr.Button("City").click(
152
- fn=lambda: "Fast drone racing through futuristic city streets --duration 5 --camerafixed false",
153
- outputs=prompt
154
  )
155
- gr.Button("Ocean").click(
156
- fn=lambda: "Drone following waves at golden hour --duration 5 --camerafixed false",
157
- outputs=prompt
158
  )
159
 
160
- # Connect the generate button
161
  generate_event = generate_btn.click(
162
  fn=generate_video,
163
  inputs=[image_input, prompt],
 
2
  import time
3
  import gradio as gr
4
  from byteplussdkarkruntime import Ark
5
+ import httpx
6
+ import socket
7
 
8
  # Get API key from Hugging Face secret "Key"
9
  API_KEY = os.environ.get("Key", "")
10
 
11
+ # Initialize client with better timeout and retry settings
12
  client = Ark(
13
  base_url="https://ark.ap-southeast.bytepluses.com/api/v3",
14
  api_key=API_KEY,
15
+ timeout=30.0, # Shorter timeout to fail faster
16
+ max_retries=3,
17
  )
18
 
19
+ # Fresh new prompts
20
+ DEFAULT_PROMPTS = {
21
+ "Cinematic Nature": "Majestic drone shot soaring above misty mountains at golden hour, sunlight breaking through clouds, cinematic 4k quality, smooth motion --duration 5 --camerafixed false",
22
+
23
+ "Urban Exploration": "Dynamic drone flight through narrow alleyways of a neon-lit Tokyo street at night, rain-slicked surfaces reflecting lights, cyberpunk aesthetic --duration 5 --camerafixed false",
24
+
25
+ "Action Sequence": "High-speed drone chasing a sports car through a winding coastal road, dramatic cliffside views, action movie style --duration 5 --camerafixed false",
26
+
27
+ "Abstract Art": "Surreal drone flight through floating geometric shapes in a dreamlike void, pastel colors, ethereal atmosphere --duration 5 --camerafixed false",
28
+
29
+ "Wildlife Documentary": "Drone following a herd of elephants across the African savanna at sunset, National Geographic style, majestic wildlife cinematography --duration 5 --camerafixed false",
30
+
31
+ "Sports Highlight": "Drone racing alongside professional skiers carving through fresh powder in the Alps, high-energy sports broadcast style --duration 5 --camerafixed false",
32
+
33
+ "Beach Paradise": "Drone gliding over turquoise waters and white sand beaches, palm trees swaying, tropical paradise aerial view --duration 5 --camerafixed false",
34
+
35
+ "Ancient Temple": "Drone circling around ancient Angkor Wat temple at dawn, mystical atmosphere, historical documentary style --duration 5 --camerafixed false"
36
+ }
37
+
38
+ def test_connection():
39
+ """Test if we can reach the API before trying"""
40
+ try:
41
+ socket.gethostbyname('ark.ap-southeast.bytepluses.com')
42
+ return True, "DNS resolved"
43
+ except Exception as e:
44
+ return False, f"DNS failed: {e}"
45
+
46
  def generate_video(image_path, prompt_text, progress=gr.Progress()):
47
+ """Generate video with robust error handling"""
48
+
49
+ # Test connection first
50
+ conn_ok, conn_msg = test_connection()
51
+ if not conn_ok:
52
+ yield f"❌ Connection Error: {conn_msg}. This might be a network restriction from Hugging Face.", None
53
+ return
54
 
55
  if not API_KEY:
56
  yield "❌ API Key not configured. Please add 'Key' secret.", None
 
63
  try:
64
  progress(0, desc="Preparing image...")
65
 
66
+ # Get HF temp URL
 
67
  image_url = f"/file={image_path}"
68
  print(f"Using image URL: {image_url}")
69
 
 
71
 
72
  progress(0.2, desc="Creating request...")
73
 
74
+ # Create task with timeout
75
+ try:
76
+ create_result = client.content_generation.tasks.create(
77
+ model="seedance-1-5-pro-251215",
78
+ content=[
79
+ {
80
+ "type": "text",
81
+ "text": prompt_text
82
+ },
83
+ {
84
+ "type": "image_url",
85
+ "image_url": {
86
+ "url": image_url
87
+ }
88
  }
89
+ ]
90
+ )
91
+ except Exception as e:
92
+ error_str = str(e)
93
+ if "Connection error" in error_str or "202602" in error_str:
94
+ yield f"❌ Network Error: Cannot reach BytePlus API. This is likely a Hugging Face network restriction.", None
95
+ else:
96
+ yield f"❌ API Error: {error_str}", None
97
+ return
98
 
99
  task_id = create_result.id
100
  print(f"Task created: {task_id}")
 
102
 
103
  progress(0.3, desc="Polling for results...")
104
 
105
+ # Poll for results
106
  attempts = 0
107
+ max_attempts = 120
108
 
109
  while attempts < max_attempts:
110
+ try:
111
+ get_result = client.content_generation.tasks.get(task_id=task_id)
112
+ status = get_result.status
 
 
 
 
 
 
 
113
 
114
+ if status == "succeeded":
115
+ progress(1.0, desc="Complete!")
116
+ video_url = get_result.content.video_url if hasattr(get_result, 'content') else None
117
+ print(f"Video URL: {video_url}")
118
+ yield "✅ Video generated successfully!", video_url
119
+ return
120
+
121
+ elif status == "failed":
122
+ error_msg = get_result.error if hasattr(get_result, 'error') else "Unknown error"
123
+ yield f"❌ Failed: {error_msg}", None
124
+ return
125
+ else:
126
+ progress(0.3 + (attempts/max_attempts)*0.7, desc=f"Status: {status}")
127
+ yield f"⏳ Status: {status}... (attempt {attempts + 1})", None
128
+ time.sleep(1)
129
+ attempts += 1
130
+
131
+ except Exception as e:
132
+ print(f"Polling error: {e}")
133
+ time.sleep(2)
134
  attempts += 1
135
 
136
  yield "⏰ Timeout after 2 minutes", None
137
 
138
  except Exception as e:
139
  print(f"Error: {e}")
140
+ if "Connection error" in str(e):
141
+ yield "❌ Connection Error: Cannot reach BytePlus API. This is likely a Hugging Face network restriction. Try running locally instead.", None
142
+ else:
143
+ yield f"❌ Error: {str(e)}", None
144
+
145
+ def update_prompt(choice):
146
+ """Update prompt when shot type changes"""
147
+ return DEFAULT_PROMPTS.get(choice, "")
148
 
149
+ # Interface
150
  with gr.Blocks(title="BytePlus Video Generator", theme=gr.themes.Soft()) as demo:
151
 
152
  gr.Markdown("""
153
  # 🎥 BytePlus Video Generator
154
+ Upload an image and choose a shot type to generate a stunning video.
 
155
  """)
156
 
157
+ # Status row
158
+ with gr.Row():
159
+ if API_KEY:
160
+ gr.Markdown("✅ **API Key:** Configured")
161
+ else:
162
+ gr.Markdown("❌ **API Key:** Not configured - please add 'Key' secret")
163
+
164
+ # Connection test button
165
+ with gr.Row():
166
+ test_btn = gr.Button("🔌 Test Connection", size="sm")
167
+ test_result = gr.Textbox(label="Connection Test", lines=1)
168
+
169
+ def run_connection_test():
170
+ ok, msg = test_connection()
171
+ return f"{'✅' if ok else '❌'} {msg}"
172
+
173
+ test_btn.click(fn=run_connection_test, outputs=test_result)
174
+
175
+ gr.Markdown("---")
176
 
177
  with gr.Row():
178
  with gr.Column():
179
+ # Image upload
180
  image_input = gr.Image(
181
  label="Upload Starting Image",
182
+ type="filepath",
183
  height=300
184
  )
185
 
186
+ # Shot type dropdown
187
+ shot_type = gr.Dropdown(
188
+ choices=list(DEFAULT_PROMPTS.keys()),
189
+ label="🎬 Shot Type",
190
+ value="Cinematic Nature"
191
+ )
192
+
193
+ # Custom prompt
194
  prompt = gr.Textbox(
195
+ label="📝 Custom Prompt (override)",
196
+ lines=3,
197
+ placeholder="Or write your own prompt here...",
198
+ value=DEFAULT_PROMPTS["Cinematic Nature"]
199
+ )
200
+
201
+ # Update prompt when shot type changes
202
+ shot_type.change(
203
+ fn=update_prompt,
204
+ inputs=shot_type,
205
+ outputs=prompt
206
  )
207
 
208
  # Generate button
 
212
  # Status
213
  status = gr.Textbox(
214
  label="Status",
215
+ lines=5,
216
  interactive=False
217
  )
218
 
 
222
  interactive=False
223
  )
224
 
225
+ # Example shots as quick buttons
226
  gr.Markdown("---")
227
+ gr.Markdown("### Quick Shot Select")
228
  with gr.Row():
229
+ gr.Button("🏔️ Nature").click(
230
+ fn=lambda: "Cinematic Nature",
231
+ outputs=shot_type
232
+ )
233
+ gr.Button("🌃 City").click(
234
+ fn=lambda: "Urban Exploration",
235
+ outputs=shot_type
236
+ )
237
+ gr.Button("🏎️ Action").click(
238
+ fn=lambda: "Action Sequence",
239
+ outputs=shot_type
240
+ )
241
+ gr.Button("🎨 Abstract").click(
242
+ fn=lambda: "Abstract Art",
243
+ outputs=shot_type
244
  )
245
+ gr.Button("🦁 Wildlife").click(
246
+ fn=lambda: "Wildlife Documentary",
247
+ outputs=shot_type
248
  )
249
+ gr.Button("⛷️ Sports").click(
250
+ fn=lambda: "Sports Highlight",
251
+ outputs=shot_type
252
  )
253
 
254
+ # Connect generate button
255
  generate_event = generate_btn.click(
256
  fn=generate_video,
257
  inputs=[image_input, prompt],