Zoe09 Claude Sonnet 4.6 commited on
Commit
55cf5ab
·
1 Parent(s): 7c65454

feat: replace Unsplash cover URLs with local assets/covers/ PNG paths

Browse files

- Add COVERS_DIR and cover_path() helper for Gradio file-serving URLs
- load_books_from_stories() uses cover_path(slug) per story filename
- player_title_info initial HTML uses cover_path() f-string instead of hardcoded Unsplash URL
- demo.queue().launch() adds allowed_paths=["assets"] for Gradio to serve local images

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Files changed (1) hide show
  1. app.py +15 -19
app.py CHANGED
@@ -4,6 +4,7 @@ import struct
4
  import wave
5
  import gradio as gr
6
  import time
 
7
 
8
  # Create directories for sample audio files
9
  os.makedirs("sample_sounds", exist_ok=True)
@@ -65,27 +66,22 @@ for key, (path, dur, mel) in create_sound_library.items():
65
  if not os.path.exists(path):
66
  generate_chimes_wav(path, duration=dur, melody_type=mel)
67
 
 
 
 
 
 
 
 
68
  def load_books_from_stories(stories_dir="stories"):
69
  books = []
70
  story_files = sorted(
71
  f for f in os.listdir(stories_dir) if f.endswith(".txt")
72
  ) if os.path.isdir(stories_dir) else []
73
 
74
- cover_urls = [
75
- "https://images.unsplash.com/photo-1544947950-fa07a98d237f?auto=format&fit=crop&q=80&w=400",
76
- "https://images.unsplash.com/photo-1512820790803-83ca734da794?auto=format&fit=crop&q=80&w=400",
77
- "https://images.unsplash.com/photo-1476275466078-4007374efbbe?auto=format&fit=crop&q=80&w=400",
78
- "https://images.unsplash.com/photo-1456513080510-7bf3a84b82f8?auto=format&fit=crop&q=80&w=400",
79
- "https://images.unsplash.com/photo-1492052722242-2554d0e99e3a?auto=format&fit=crop&q=80&w=400",
80
- "https://images.unsplash.com/photo-1474932430478-367dbb6832c1?auto=format&fit=crop&q=80&w=400",
81
- "https://images.unsplash.com/photo-1456513080510-7bf3a84b82f8?auto=format&fit=crop&q=80&w=400",
82
- "https://images.unsplash.com/photo-1495640388908-05fa85288e61?auto=format&fit=crop&q=80&w=400",
83
- "https://images.unsplash.com/photo-1476275466078-4007374efbbe?auto=format&fit=crop&q=80&w=400",
84
- "https://images.unsplash.com/photo-1512820790803-83ca734da794?auto=format&fit=crop&q=80&w=400",
85
- ]
86
-
87
  for i, filename in enumerate(story_files):
88
  title = filename.replace(".txt", "").replace("_", " ")
 
89
  # Read first non-empty line as synopsis opener
90
  synopsis = ""
91
  try:
@@ -99,7 +95,7 @@ def load_books_from_stories(stories_dir="stories"):
99
  "id": str(i + 1),
100
  "title": title,
101
  "author": "Public Domain",
102
- "cover_url": cover_urls[i % len(cover_urls)],
103
  "voice_name": "Mom’s Voice",
104
  "duration": 0,
105
  "elapsed_time": 0,
@@ -462,11 +458,11 @@ with gr.Blocks(css=css_code, title="VoiceBook Gradio Hub") as demo:
462
  )
463
  player_load_btn = gr.Button("Load Story", variant="secondary", size="sm")
464
 
465
- player_title_info = gr.HTML("""
466
  <div style="text-align: center; margin-bottom: 24px; margin-top: 16px;">
467
- <img src="https://images.unsplash.com/photo-1544947950-fa07a98d237f?auto=format&fit=crop&q=80&w=400" style="width: 130px; height: 180px; object-fit: cover; border-radius: 12px; box-shadow: 0 4px 16px rgba(0,0,0,0.4); margin-bottom: 16px;" />
468
- <h3 style="font-family: 'Playfair Display', Georgia, serif; font-size: 22px; margin:0; color:#FAF7F2;">The Enchanted Willow</h3>
469
- <p style="font-size: 12px; color: #94a3b8; font-style: italic; margin-top:2px;">by Elena S. Thorne</p>
470
  <span style="display: inline-block; background: rgba(245, 132, 31, 0.15); color: #ffd3a6; font-size: 10.5px; font-weight: 700; padding: 3px 8px; border-radius: 999px; margin-top: 8px;">Active Narrator: Mom's Voice</span>
471
  </div>
472
  """)
@@ -1011,4 +1007,4 @@ with gr.Blocks(css=css_code, title="VoiceBook Gradio Hub") as demo:
1011
 
1012
  # Launch parameters configured for standard port and auto binding
1013
  if __name__ == "__main__":
1014
- demo.queue().launch()
 
4
  import wave
5
  import gradio as gr
6
  import time
7
+ from pathlib import Path
8
 
9
  # Create directories for sample audio files
10
  os.makedirs("sample_sounds", exist_ok=True)
 
66
  if not os.path.exists(path):
67
  generate_chimes_wav(path, duration=dur, melody_type=mel)
68
 
69
+ COVERS_DIR = Path("assets/covers")
70
+
71
+ def cover_path(slug: str) -> str:
72
+ """로컬 커버 이미지를 Gradio file-serving URL로 반환."""
73
+ p = COVERS_DIR / f"{slug}.png"
74
+ return f"/gradio_api/file={p.as_posix()}"
75
+
76
  def load_books_from_stories(stories_dir="stories"):
77
  books = []
78
  story_files = sorted(
79
  f for f in os.listdir(stories_dir) if f.endswith(".txt")
80
  ) if os.path.isdir(stories_dir) else []
81
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  for i, filename in enumerate(story_files):
83
  title = filename.replace(".txt", "").replace("_", " ")
84
+ slug = filename.replace(".txt", "")
85
  # Read first non-empty line as synopsis opener
86
  synopsis = ""
87
  try:
 
95
  "id": str(i + 1),
96
  "title": title,
97
  "author": "Public Domain",
98
+ "cover_url": cover_path(slug),
99
  "voice_name": "Mom’s Voice",
100
  "duration": 0,
101
  "elapsed_time": 0,
 
458
  )
459
  player_load_btn = gr.Button("Load Story", variant="secondary", size="sm")
460
 
461
+ player_title_info = gr.HTML(f"""
462
  <div style="text-align: center; margin-bottom: 24px; margin-top: 16px;">
463
+ <img src="{cover_path('The_Adventures_of_Puss_in_Boots')}" style="width: 130px; height: 180px; object-fit: cover; border-radius: 12px; box-shadow: 0 4px 16px rgba(0,0,0,0.4); margin-bottom: 16px;" />
464
+ <h3 style="font-family: 'Playfair Display', Georgia, serif; font-size: 22px; margin:0; color:#FAF7F2;">Select a Story</h3>
465
+ <p style="font-size: 12px; color: #94a3b8; font-style: italic; margin-top:2px;">Choose a story above and press Load</p>
466
  <span style="display: inline-block; background: rgba(245, 132, 31, 0.15); color: #ffd3a6; font-size: 10.5px; font-weight: 700; padding: 3px 8px; border-radius: 999px; margin-top: 8px;">Active Narrator: Mom's Voice</span>
467
  </div>
468
  """)
 
1007
 
1008
  # Launch parameters configured for standard port and auto binding
1009
  if __name__ == "__main__":
1010
+ demo.queue().launch(allowed_paths=["assets"])