Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -17,7 +17,7 @@ import contextlib
|
|
17 |
import asyncio
|
18 |
import uuid # For unique identifiers
|
19 |
import shutil # For directory operations
|
20 |
-
import logging
|
21 |
|
22 |
# Image handling
|
23 |
from PIL import Image
|
@@ -36,7 +36,7 @@ import typing_extensions as typing
|
|
36 |
import nest_asyncio
|
37 |
nest_asyncio.apply()
|
38 |
|
39 |
-
# Import Vertex AI SDK and service account credentials support
|
40 |
import vertexai
|
41 |
from vertexai.preview.vision_models import ImageGenerationModel
|
42 |
from google.oauth2 import service_account
|
@@ -84,14 +84,13 @@ except KeyError:
|
|
84 |
st.error("π¨ **Google API Key Not Found!** Please configure it.", icon="π¨")
|
85 |
st.stop()
|
86 |
|
87 |
-
# Vertex AI configuration: PROJECT_ID and LOCATION
|
88 |
PROJECT_ID = st.secrets.get("PROJECT_ID") or os.environ.get("PROJECT_ID")
|
89 |
LOCATION = st.secrets.get("LOCATION") or os.environ.get("LOCATION", "us-central1")
|
90 |
if not PROJECT_ID:
|
91 |
st.error("π¨ **PROJECT_ID not set!** Please add PROJECT_ID to your secrets.", icon="π¨")
|
92 |
st.stop()
|
93 |
|
94 |
-
# Load service account JSON from
|
95 |
try:
|
96 |
service_account_info = json.loads(os.environ["SERVICE_ACCOUNT_JSON"])
|
97 |
credentials = service_account.Credentials.from_service_account_info(service_account_info)
|
@@ -175,7 +174,6 @@ def wave_file_writer(filename: str, channels: int = 1, rate: int = AUDIO_SAMPLIN
|
|
175 |
logger.error(f"Error closing wave file {filename}: {e_close}")
|
176 |
|
177 |
# --- Audio Generation using gTTS ---
|
178 |
-
# We replace the previous failing method with gTTS.
|
179 |
async def generate_audio_live_async(api_text: str, output_filename: str, voice: Optional[str] = None) -> Optional[str]:
|
180 |
"""
|
181 |
Generates audio using gTTS (Google Text-to-Speech).
|
@@ -184,16 +182,18 @@ async def generate_audio_live_async(api_text: str, output_filename: str, voice:
|
|
184 |
task_id = os.path.basename(output_filename).split('.')[0]
|
185 |
logger.info(f"ποΈ [{task_id}] Generating audio via gTTS for text: '{api_text[:60]}...'")
|
186 |
try:
|
187 |
-
# Generate audio using gTTS
|
188 |
tts = gTTS(text=api_text, lang="en")
|
189 |
-
# Replace .wav with .mp3
|
190 |
mp3_filename = output_filename.replace(".wav", ".mp3")
|
191 |
tts.save(mp3_filename)
|
192 |
logger.info(f"β
[{task_id}] Audio saved: {os.path.basename(mp3_filename)}")
|
193 |
return mp3_filename
|
194 |
except Exception as e:
|
|
|
|
|
|
|
|
|
|
|
195 |
logger.exception(f"β [{task_id}] Audio generation error: {e}")
|
196 |
-
st.error(f"Audio generation failed for {task_id}: {e}", icon="π")
|
197 |
return None
|
198 |
|
199 |
def generate_story_sequence_chrono(theme: str, num_scenes: int, num_timelines: int, divergence_prompt: str = "") -> Optional[ChronoWeaveResponse]:
|
@@ -258,8 +258,8 @@ def generate_image_imagen(prompt: str, aspect_ratio: str = "1:1", task_id: str =
|
|
258 |
"""
|
259 |
Generates an image using Vertex AI's Imagen model via the Vertex AI preview API.
|
260 |
|
261 |
-
|
262 |
-
If
|
263 |
"""
|
264 |
logger.info(f"πΌοΈ [{task_id}] Requesting image: '{prompt[:70]}...' (Aspect: {aspect_ratio})")
|
265 |
try:
|
@@ -278,12 +278,10 @@ def generate_image_imagen(prompt: str, aspect_ratio: str = "1:1", task_id: str =
|
|
278 |
return image
|
279 |
except Exception as e:
|
280 |
error_str = str(e)
|
281 |
-
if "
|
282 |
error_msg = (
|
283 |
-
"
|
284 |
-
"
|
285 |
-
"For example, on Hugging Face Spaces, set SERVICE_ACCOUNT_JSON in your repository secrets. "
|
286 |
-
"If running locally, run `!gcloud auth login`."
|
287 |
)
|
288 |
else:
|
289 |
error_msg = f"Image generation for {task_id} failed: {e}"
|
@@ -382,7 +380,6 @@ if generate_button:
|
|
382 |
generated_audio_path: Optional[str] = None
|
383 |
if not scene_has_error:
|
384 |
with st.spinner(f"[{task_id}] Generating audio... π"):
|
385 |
-
# Change output extension to .wav for consistency, but gTTS returns MP3
|
386 |
audio_path_temp = os.path.join(temp_dir, f"{task_id}_audio.wav")
|
387 |
try:
|
388 |
generated_audio_path = asyncio.run(generate_audio_live_async(segment.audio_text, audio_path_temp, audio_voice))
|
|
|
17 |
import asyncio
|
18 |
import uuid # For unique identifiers
|
19 |
import shutil # For directory operations
|
20 |
+
import logging
|
21 |
|
22 |
# Image handling
|
23 |
from PIL import Image
|
|
|
36 |
import nest_asyncio
|
37 |
nest_asyncio.apply()
|
38 |
|
39 |
+
# Import Vertex AI SDK and Google service account credentials support
|
40 |
import vertexai
|
41 |
from vertexai.preview.vision_models import ImageGenerationModel
|
42 |
from google.oauth2 import service_account
|
|
|
84 |
st.error("π¨ **Google API Key Not Found!** Please configure it.", icon="π¨")
|
85 |
st.stop()
|
86 |
|
|
|
87 |
PROJECT_ID = st.secrets.get("PROJECT_ID") or os.environ.get("PROJECT_ID")
|
88 |
LOCATION = st.secrets.get("LOCATION") or os.environ.get("LOCATION", "us-central1")
|
89 |
if not PROJECT_ID:
|
90 |
st.error("π¨ **PROJECT_ID not set!** Please add PROJECT_ID to your secrets.", icon="π¨")
|
91 |
st.stop()
|
92 |
|
93 |
+
# Load service account JSON from secret and create credentials
|
94 |
try:
|
95 |
service_account_info = json.loads(os.environ["SERVICE_ACCOUNT_JSON"])
|
96 |
credentials = service_account.Credentials.from_service_account_info(service_account_info)
|
|
|
174 |
logger.error(f"Error closing wave file {filename}: {e_close}")
|
175 |
|
176 |
# --- Audio Generation using gTTS ---
|
|
|
177 |
async def generate_audio_live_async(api_text: str, output_filename: str, voice: Optional[str] = None) -> Optional[str]:
|
178 |
"""
|
179 |
Generates audio using gTTS (Google Text-to-Speech).
|
|
|
182 |
task_id = os.path.basename(output_filename).split('.')[0]
|
183 |
logger.info(f"ποΈ [{task_id}] Generating audio via gTTS for text: '{api_text[:60]}...'")
|
184 |
try:
|
|
|
185 |
tts = gTTS(text=api_text, lang="en")
|
|
|
186 |
mp3_filename = output_filename.replace(".wav", ".mp3")
|
187 |
tts.save(mp3_filename)
|
188 |
logger.info(f"β
[{task_id}] Audio saved: {os.path.basename(mp3_filename)}")
|
189 |
return mp3_filename
|
190 |
except Exception as e:
|
191 |
+
error_str = str(e)
|
192 |
+
if "429" in error_str:
|
193 |
+
st.error(f"Audio generation for {task_id} failed: 429 Too Many Requests from TTS API. Please try again later.", icon="π")
|
194 |
+
else:
|
195 |
+
st.error(f"Audio generation for {task_id} failed: {e}", icon="π")
|
196 |
logger.exception(f"β [{task_id}] Audio generation error: {e}")
|
|
|
197 |
return None
|
198 |
|
199 |
def generate_story_sequence_chrono(theme: str, num_scenes: int, num_timelines: int, divergence_prompt: str = "") -> Optional[ChronoWeaveResponse]:
|
|
|
258 |
"""
|
259 |
Generates an image using Vertex AI's Imagen model via the Vertex AI preview API.
|
260 |
|
261 |
+
Loads the pretrained Imagen model and attempts to generate an image.
|
262 |
+
If a quota exceeded error occurs, it informs you to request a quota increase.
|
263 |
"""
|
264 |
logger.info(f"πΌοΈ [{task_id}] Requesting image: '{prompt[:70]}...' (Aspect: {aspect_ratio})")
|
265 |
try:
|
|
|
278 |
return image
|
279 |
except Exception as e:
|
280 |
error_str = str(e)
|
281 |
+
if "Quota exceeded" in error_str:
|
282 |
error_msg = (
|
283 |
+
"Quota exceeded for image generation requests. "
|
284 |
+
"Please submit a quota increase request via the Vertex AI console: https://cloud.google.com/vertex-ai/docs/generative-ai/quotas-genai"
|
|
|
|
|
285 |
)
|
286 |
else:
|
287 |
error_msg = f"Image generation for {task_id} failed: {e}"
|
|
|
380 |
generated_audio_path: Optional[str] = None
|
381 |
if not scene_has_error:
|
382 |
with st.spinner(f"[{task_id}] Generating audio... π"):
|
|
|
383 |
audio_path_temp = os.path.join(temp_dir, f"{task_id}_audio.wav")
|
384 |
try:
|
385 |
generated_audio_path = asyncio.run(generate_audio_live_async(segment.audio_text, audio_path_temp, audio_voice))
|