Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -105,66 +105,66 @@ import httpx
|
|
| 105 |
import tempfile
|
| 106 |
import asyncio
|
| 107 |
|
| 108 |
-
async def download_file_from_url(url: str, retries: int = 3, delay: float = 2.0) -> str | None:
|
| 109 |
-
"""
|
| 110 |
-
Downloads a file from a URL and returns the path to a temporary file.
|
| 111 |
-
Retries on failure up to `retries` times, waiting `delay` seconds between attempts.
|
| 112 |
-
Returns None if all attempts fail.
|
| 113 |
-
"""
|
| 114 |
-
for attempt in range(1, retries + 1):
|
| 115 |
-
try:
|
| 116 |
-
async with httpx.AsyncClient(timeout=60.0) as client: # increased timeout
|
| 117 |
-
response = await client.get(url)
|
| 118 |
-
response.raise_for_status() # raises for non-200 status codes
|
| 119 |
-
|
| 120 |
-
# Save to a temporary file
|
| 121 |
-
temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".wav")
|
| 122 |
-
temp_file.write(response.content)
|
| 123 |
-
temp_file.close()
|
| 124 |
-
print(f"Downloaded {url} successfully on attempt {attempt}")
|
| 125 |
-
return temp_file.name
|
| 126 |
-
|
| 127 |
-
except Exception as e:
|
| 128 |
-
print(f"Attempt {attempt} failed for {url}: {e}")
|
| 129 |
-
if attempt < retries:
|
| 130 |
-
await asyncio.sleep(delay) # wait before retrying
|
| 131 |
-
|
| 132 |
-
print(f"All {retries} attempts failed for {url}")
|
| 133 |
-
return None
|
| 134 |
-
|
| 135 |
-
# download_cache = {}
|
| 136 |
-
|
| 137 |
# async def download_file_from_url(url: str, retries: int = 3, delay: float = 2.0) -> str | None:
|
| 138 |
# """
|
| 139 |
# Downloads a file from a URL and returns the path to a temporary file.
|
| 140 |
-
#
|
| 141 |
-
#
|
| 142 |
# """
|
| 143 |
-
# if url in download_cache:
|
| 144 |
-
# print(f"{url} is got from cache")
|
| 145 |
-
# return download_cache[url]
|
| 146 |
-
|
| 147 |
# for attempt in range(1, retries + 1):
|
| 148 |
# try:
|
| 149 |
-
# async with httpx.AsyncClient(timeout=60.0) as client:
|
| 150 |
# response = await client.get(url)
|
| 151 |
-
# response.raise_for_status()
|
| 152 |
|
|
|
|
| 153 |
# temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".wav")
|
| 154 |
# temp_file.write(response.content)
|
| 155 |
# temp_file.close()
|
| 156 |
-
|
| 157 |
-
# download_cache[url] = temp_file.name
|
| 158 |
# return temp_file.name
|
| 159 |
|
| 160 |
# except Exception as e:
|
| 161 |
# print(f"Attempt {attempt} failed for {url}: {e}")
|
| 162 |
# if attempt < retries:
|
| 163 |
-
# await asyncio.sleep(delay)
|
| 164 |
|
| 165 |
-
# print(f"All {retries} attempts failed for {url}
|
| 166 |
# return None
|
| 167 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 168 |
#-----------------------------------------------------------
|
| 169 |
|
| 170 |
#takes the text to be said and path to the prosody audio and path to save the generated audio and returns path to the generated audio
|
|
@@ -215,7 +215,7 @@ async def generate_story_audios(story: StoryCreationDTO, base_output: str):
|
|
| 215 |
audio_file=prosody_file_title,
|
| 216 |
save_path=title_save_path
|
| 217 |
)
|
| 218 |
-
os.remove(prosody_file_title)
|
| 219 |
|
| 220 |
for scene in chapter.scenes:
|
| 221 |
scene_dir = chapter_dir / scene.sceneId
|
|
@@ -236,7 +236,7 @@ async def generate_story_audios(story: StoryCreationDTO, base_output: str):
|
|
| 236 |
audio_file=prosody_file,
|
| 237 |
save_path=sentence_save_path
|
| 238 |
)
|
| 239 |
-
os.remove(prosody_file)
|
| 240 |
|
| 241 |
#_______________ Concatenating the generated audios to make the final story (post-processing)_______________________
|
| 242 |
|
|
@@ -295,7 +295,7 @@ async def concat_story_audio(story: StoryCreationDTO, base_output: str, final_pa
|
|
| 295 |
sfx_file_wav = ensure_wav(sfx_file)
|
| 296 |
sfx_audio = AudioSegment.from_wav(sfx_file_wav)
|
| 297 |
scene_audio = scene_audio.overlay(sfx_audio)
|
| 298 |
-
os.remove(sfx_file)
|
| 299 |
else:
|
| 300 |
print(f"SFX skipped for {scene.location.locationName}")
|
| 301 |
|
|
@@ -314,7 +314,7 @@ async def concat_story_audio(story: StoryCreationDTO, base_output: str, final_pa
|
|
| 314 |
bg_audio = bg_audio * loops
|
| 315 |
bg_audio = bg_audio[:len(scene_audio)] # trim to match scene
|
| 316 |
scene_audio = scene_audio.overlay(bg_audio)
|
| 317 |
-
os.remove(bg_file)
|
| 318 |
|
| 319 |
# Add 2 seconds of silence between scenes
|
| 320 |
scene_audio += AudioSegment.silent(duration=2000)
|
|
@@ -534,6 +534,12 @@ async def get_results(task_id: str):
|
|
| 534 |
# Ensure result exists and has all required fields
|
| 535 |
result = task.get("result")
|
| 536 |
if result and all(k in result for k in ("fileName", "duration", "audioBase64")):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 537 |
return {"status": "completed", **result}
|
| 538 |
else:
|
| 539 |
# If result is missing fields, mark as still processing
|
|
|
|
| 105 |
import tempfile
|
| 106 |
import asyncio
|
| 107 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 108 |
# async def download_file_from_url(url: str, retries: int = 3, delay: float = 2.0) -> str | None:
|
| 109 |
# """
|
| 110 |
# Downloads a file from a URL and returns the path to a temporary file.
|
| 111 |
+
# Retries on failure up to `retries` times, waiting `delay` seconds between attempts.
|
| 112 |
+
# Returns None if all attempts fail.
|
| 113 |
# """
|
|
|
|
|
|
|
|
|
|
|
|
|
| 114 |
# for attempt in range(1, retries + 1):
|
| 115 |
# try:
|
| 116 |
+
# async with httpx.AsyncClient(timeout=60.0) as client: # increased timeout
|
| 117 |
# response = await client.get(url)
|
| 118 |
+
# response.raise_for_status() # raises for non-200 status codes
|
| 119 |
|
| 120 |
+
# # Save to a temporary file
|
| 121 |
# temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".wav")
|
| 122 |
# temp_file.write(response.content)
|
| 123 |
# temp_file.close()
|
| 124 |
+
# print(f"Downloaded {url} successfully on attempt {attempt}")
|
|
|
|
| 125 |
# return temp_file.name
|
| 126 |
|
| 127 |
# except Exception as e:
|
| 128 |
# print(f"Attempt {attempt} failed for {url}: {e}")
|
| 129 |
# if attempt < retries:
|
| 130 |
+
# await asyncio.sleep(delay) # wait before retrying
|
| 131 |
|
| 132 |
+
# print(f"All {retries} attempts failed for {url}")
|
| 133 |
# return None
|
| 134 |
|
| 135 |
+
download_cache = {}
|
| 136 |
+
|
| 137 |
+
async def download_file_from_url(url: str, retries: int = 3, delay: float = 2.0) -> str | None:
|
| 138 |
+
"""
|
| 139 |
+
Downloads a file from a URL and returns the path to a temporary file.
|
| 140 |
+
If download fails after `retries` attempts, returns None instead of raising an error.
|
| 141 |
+
Caches successful downloads to avoid repeated requests.
|
| 142 |
+
"""
|
| 143 |
+
if url in download_cache:
|
| 144 |
+
print(f"{url} is got from cache")
|
| 145 |
+
return download_cache[url]
|
| 146 |
+
|
| 147 |
+
for attempt in range(1, retries + 1):
|
| 148 |
+
try:
|
| 149 |
+
async with httpx.AsyncClient(timeout=60.0) as client:
|
| 150 |
+
response = await client.get(url)
|
| 151 |
+
response.raise_for_status()
|
| 152 |
+
|
| 153 |
+
temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".wav")
|
| 154 |
+
temp_file.write(response.content)
|
| 155 |
+
temp_file.close()
|
| 156 |
+
|
| 157 |
+
download_cache[url] = temp_file.name
|
| 158 |
+
return temp_file.name
|
| 159 |
+
|
| 160 |
+
except Exception as e:
|
| 161 |
+
print(f"Attempt {attempt} failed for {url}: {e}")
|
| 162 |
+
if attempt < retries:
|
| 163 |
+
await asyncio.sleep(delay)
|
| 164 |
+
|
| 165 |
+
print(f"All {retries} attempts failed for {url}, skipping...")
|
| 166 |
+
return None
|
| 167 |
+
|
| 168 |
#-----------------------------------------------------------
|
| 169 |
|
| 170 |
#takes the text to be said and path to the prosody audio and path to save the generated audio and returns path to the generated audio
|
|
|
|
| 215 |
audio_file=prosody_file_title,
|
| 216 |
save_path=title_save_path
|
| 217 |
)
|
| 218 |
+
# os.remove(prosody_file_title)
|
| 219 |
|
| 220 |
for scene in chapter.scenes:
|
| 221 |
scene_dir = chapter_dir / scene.sceneId
|
|
|
|
| 236 |
audio_file=prosody_file,
|
| 237 |
save_path=sentence_save_path
|
| 238 |
)
|
| 239 |
+
# os.remove(prosody_file)
|
| 240 |
|
| 241 |
#_______________ Concatenating the generated audios to make the final story (post-processing)_______________________
|
| 242 |
|
|
|
|
| 295 |
sfx_file_wav = ensure_wav(sfx_file)
|
| 296 |
sfx_audio = AudioSegment.from_wav(sfx_file_wav)
|
| 297 |
scene_audio = scene_audio.overlay(sfx_audio)
|
| 298 |
+
# os.remove(sfx_file)
|
| 299 |
else:
|
| 300 |
print(f"SFX skipped for {scene.location.locationName}")
|
| 301 |
|
|
|
|
| 314 |
bg_audio = bg_audio * loops
|
| 315 |
bg_audio = bg_audio[:len(scene_audio)] # trim to match scene
|
| 316 |
scene_audio = scene_audio.overlay(bg_audio)
|
| 317 |
+
# os.remove(bg_file)
|
| 318 |
|
| 319 |
# Add 2 seconds of silence between scenes
|
| 320 |
scene_audio += AudioSegment.silent(duration=2000)
|
|
|
|
| 534 |
# Ensure result exists and has all required fields
|
| 535 |
result = task.get("result")
|
| 536 |
if result and all(k in result for k in ("fileName", "duration", "audioBase64")):
|
| 537 |
+
#clearing cache
|
| 538 |
+
for file_path in download_cache.values():
|
| 539 |
+
if os.path.exists(file_path):
|
| 540 |
+
os.remove(file_path)
|
| 541 |
+
download_cache.clear()
|
| 542 |
+
|
| 543 |
return {"status": "completed", **result}
|
| 544 |
else:
|
| 545 |
# If result is missing fields, mark as still processing
|