Sunghyun Jun commited on
Commit
431ceed
Β·
1 Parent(s): ef15d8b

Update generate_speech demo

Browse files
Files changed (1) hide show
  1. app.py +175 -56
app.py CHANGED
@@ -1,70 +1,189 @@
1
- import gradio as gr
2
  import requests
 
3
  import os
4
- import json
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- PRIVATE_SPACE_URL = os.getenv("PRIVATE_SPACE_URL")
7
- HF_TOKEN = os.getenv("HF_TOKEN")
 
 
 
8
 
9
- def fetch_actor_data():
10
- if not PRIVATE_SPACE_URL:
11
- return "Error: PRIVATE_SPACE_URL not found. Check Secrets."
12
- if not HF_TOKEN:
13
- return "Error: HF_TOKEN not found. Check Secrets."
14
 
 
 
 
 
 
15
  headers = {
16
- "Authorization": f"Bearer {HF_TOKEN}"
 
 
 
 
 
 
 
 
 
17
  }
18
 
 
 
19
  try:
20
- response = requests.get(f"{PRIVATE_SPACE_URL}/api/actor", headers=headers)
 
 
 
 
 
 
 
 
 
21
 
22
- if response.status_code == 200:
23
- # 응닡 JSON νŒŒμ‹±
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  data = response.json()
25
-
26
- # κΈ°λŒ€ ꡬ쑰: data["data"]["result"] => list of actor items
27
- actor_ids = []
28
- if (
29
- "data" in data
30
- and isinstance(data["data"], dict)
31
- and "result" in data["data"]
32
- and isinstance(data["data"]["result"], list)
33
- ):
34
- for item in data["data"]["result"]:
35
- if "actor_id" in item:
36
- actor_ids.append(item["actor_id"])
37
- if len(actor_ids) >= 10:
38
- break
39
-
40
- if actor_ids:
41
- return f"Found actor_ids: {actor_ids}"
42
- else:
43
- # actor_idκ°€ 없을 경우 ꡬ쑰 νŒŒμ•…μš© λ°˜ν™˜
44
- top_level_keys = list(data["data"].keys()) if "data" in data and isinstance(data["data"], dict) else []
45
- first_item = data["data"]["result"][0] if "data" in data and "result" in data["data"] and len(data["data"]["result"]) > 0 else {}
46
- return (
47
- "No actor_id found.\n\n"
48
- f"Keys in data['data']: {top_level_keys}\n\n"
49
- "First item in data['data']['result']:\n" +
50
- json.dumps(first_item, indent=2, ensure_ascii=False)
51
- )
52
- else:
53
- return f"Error {response.status_code}\nResponse Text:\n{response.text}"
54
- except Exception as e:
55
- return f"Request failed: {str(e)}"
56
-
57
- iface = gr.Interface(
58
- fn=fetch_actor_data,
59
- inputs=None,
60
- outputs="text",
61
- title="Fetch Actor Data",
62
- description=(
63
- "Fetches actor data from the private Hugging Face Space.\n"
64
- "Assumes structure: {status_code:..., data:{count:..., result:[{actor_id:...}]}}\n"
65
- "If no actor_id found, shows partial keys for debugging."
66
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  )
68
 
69
  if __name__ == "__main__":
70
- iface.launch()
 
 
1
  import requests
2
+ import gradio as gr
3
  import os
4
+ import time
5
+
6
+ # ν™˜κ²½ λ³€μˆ˜ μ΄ˆκΈ°ν™” 및 검증
7
+ def initialize_environment():
8
+ private_space_url = os.getenv("PRIVATE_SPACE_URL")
9
+ hf_token = os.getenv("HF_TOKEN")
10
+
11
+ if not private_space_url:
12
+ raise EnvironmentError("PRIVATE_SPACE_URL ν™˜κ²½ λ³€μˆ˜κ°€ μ„€μ •λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.")
13
+ if not hf_token:
14
+ raise EnvironmentError("HF_TOKEN ν™˜κ²½ λ³€μˆ˜κ°€ μ„€μ •λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.")
15
+
16
+ return private_space_url, hf_token
17
+
18
+ PRIVATE_SPACE_URL, HF_TOKEN = initialize_environment()
19
+
20
+ # Base URL둜 GET μš”μ²­ λ³΄λ‚΄λŠ” ν•¨μˆ˜
21
+ def test_base_url():
22
+ headers = {"Authorization": f"Bearer {HF_TOKEN}"}
23
+ print(f"[DEBUG] Sending GET request to base URL: {PRIVATE_SPACE_URL}")
24
+ print(f"[DEBUG] HF Token: {HF_TOKEN}")
25
+ try:
26
+ response = requests.get(PRIVATE_SPACE_URL, headers=headers)
27
+ print(f"[DEBUG] Base URL Response Status Code: {response.status_code}")
28
+ except requests.exceptions.RequestException as e:
29
+ print(f"[ERROR] Base URL μš”μ²­ 쀑 였λ₯˜ λ°œμƒ: {e}")
30
+
31
+ # Actor ID 쑰회 ν•¨μˆ˜
32
+ def fetch_actor_ids():
33
+ url = f"{PRIVATE_SPACE_URL}/api/actor"
34
+ headers = {"Authorization": f"Bearer {HF_TOKEN}"}
35
+ try:
36
+ response = requests.get(url, headers=headers)
37
+ response.raise_for_status()
38
+ data = response.json()
39
+
40
+ # Actor λ¦¬μŠ€νŠΈμ—μ„œ 이름과 ID μΆ”μΆœ
41
+ return {
42
+ actor["name"]["en"]: actor["actor_id"]
43
+ for actor in data.get("result", [])
44
+ }
45
+ except requests.exceptions.RequestException as e:
46
+ print(f"[ERROR] Actor ID 쑰회 쀑 였λ₯˜ λ°œμƒ: {e}")
47
+ return {}
48
 
49
+ # URL μΉ˜ν™˜ ν•¨μˆ˜
50
+ def replace_speak_url(url):
51
+ if not url:
52
+ return None
53
+ return url.replace("https://create-test.icepeak.ai", PRIVATE_SPACE_URL)
54
 
55
+ # μŒμ„± 생성 ν•¨μˆ˜
56
+ def generate_speech(text, actor_name, lang="en", speed_x=1.0, volume=100):
57
+ actor_ids = fetch_actor_ids()
58
+ if not actor_ids:
59
+ return "Actor λͺ©λ‘μ„ κ°€μ Έμ˜€λŠ” 데 μ‹€νŒ¨ν–ˆμŠ΅λ‹ˆλ‹€.", None
60
 
61
+ actor_id = actor_ids.get(actor_name)
62
+ if not actor_id:
63
+ return "μ„ νƒν•œ Actorλ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.", None
64
+
65
+ url = f"{PRIVATE_SPACE_URL}/api/speak"
66
  headers = {
67
+ "Authorization": f"Bearer {HF_TOKEN}",
68
+ "Content-Type": "application/json"
69
+ }
70
+ payload = {
71
+ "actor_id": actor_id,
72
+ "lang": lang,
73
+ "text": text,
74
+ "speed_x": speed_x,
75
+ "volume": volume,
76
+ "tts_mode": "actor"
77
  }
78
 
79
+ print(f"[DEBUG] Sending speech generation request to: {url}")
80
+ print(f"[DEBUG] Payload: {payload}")
81
  try:
82
+ response = requests.post(url, json=payload, headers=headers)
83
+ print(f"[DEBUG] Response Status Code: {response.status_code}")
84
+ print(f"[DEBUG] Response Content: {response.text}")
85
+ response.raise_for_status()
86
+ data = response.json()
87
+ print(f"[DEBUG] Response Data: {data}")
88
+
89
+ speak_url = replace_speak_url(data.get("result", {}).get("speak_url"))
90
+ if not speak_url:
91
+ return "였λ₯˜: μœ νš¨ν•œ speak_url을 λ°˜ν™˜ν•˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.", None
92
 
93
+ # Polling for audio generation completion
94
+ audio_url = poll_audio_url(speak_url)
95
+ if not audio_url:
96
+ return "였λ₯˜: μ˜€λ””μ˜€ λ‹€μš΄λ‘œλ“œ URL을 κ°€μ Έμ˜¬ 수 μ—†μŠ΅λ‹ˆλ‹€.", None
97
+
98
+ # Download the audio file
99
+ audio_content = download_audio(audio_url)
100
+ if not audio_content:
101
+ return "였λ₯˜: μŒμ„± νŒŒμΌμ„ λ‹€μš΄λ‘œλ“œν•  수 μ—†μŠ΅λ‹ˆλ‹€.", None
102
+
103
+ # Save the audio content to a temporary file
104
+ audio_file_path = "temp_audio.wav"
105
+ with open(audio_file_path, "wb") as audio_file:
106
+ audio_file.write(audio_content)
107
+
108
+ # Print debug information
109
+ file_size = os.path.getsize(audio_file_path)
110
+ print(f"[DEBUG] Saved audio file: {audio_file_path}, Size: {file_size} bytes")
111
+
112
+ return "μŒμ„±μ΄ μ„±κ³΅μ μœΌλ‘œ μƒμ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€.", audio_file_path
113
+ except requests.exceptions.RequestException as e:
114
+ print(f"[ERROR] μŒμ„± 생성 쀑 였λ₯˜ λ°œμƒ: {e}")
115
+ return f"였λ₯˜: {str(e)}", None
116
+
117
+ # Polling ν•¨μˆ˜
118
+ def poll_audio_url(speak_url, timeout=30, interval=2):
119
+ headers = {"Authorization": f"Bearer {HF_TOKEN}"}
120
+ start_time = time.time()
121
+
122
+ while time.time() - start_time < timeout:
123
+ try:
124
+ print(f"[DEBUG] Polling speak URL: {speak_url}")
125
+ response = requests.get(speak_url, headers=headers)
126
+ response.raise_for_status()
127
  data = response.json()
128
+ status = data.get("result", {}).get("status")
129
+ if status == "done":
130
+ audio_info = data.get("result", {}).get("audio", {})
131
+ audio_url = replace_speak_url(audio_info.get("url"))
132
+ print(f"[DEBUG] Audio URL: {audio_url}")
133
+ return audio_url
134
+ except requests.exceptions.RequestException as e:
135
+ print(f"[DEBUG] Polling attempt failed: {e}")
136
+ time.sleep(interval)
137
+
138
+ print("[ERROR] Polling timed out.")
139
+ return None
140
+
141
+ # Audio λ‹€μš΄λ‘œλ“œ ν•¨μˆ˜
142
+ def download_audio(audio_url):
143
+ headers = {"Authorization": f"Bearer {HF_TOKEN}"}
144
+ try:
145
+ print(f"[DEBUG] Downloading audio from: {audio_url}")
146
+ response = requests.get(audio_url, headers=headers, stream=True)
147
+ response.raise_for_status()
148
+ return response.content
149
+ except requests.exceptions.RequestException as e:
150
+ print(f"[ERROR] Audio λ‹€μš΄λ‘œλ“œ 쀑 였λ₯˜ λ°œμƒ: {e}")
151
+ return None
152
+
153
+ # Gradio μΈν„°νŽ˜μ΄μŠ€ ν•¨μˆ˜
154
+ def interface_function(text, actor_name, lang, speed_x, volume):
155
+ result_message, audio_file_path = generate_speech(text, actor_name, lang, speed_x, volume)
156
+ if audio_file_path:
157
+ return result_message, audio_file_path
158
+ return result_message, None
159
+
160
+ # Fetch actors to populate dropdown
161
+ actors = fetch_actor_ids()
162
+ actor_names = list(actors.keys())
163
+
164
+ if not actor_names:
165
+ print("[WARNING] Actor λͺ©λ‘μ„ κ°€μ Έμ˜¬ 수 μ—†μ–΄ κΈ°λ³Έ μ˜΅μ…˜μ΄ μ„€μ •λ©λ‹ˆλ‹€.")
166
+
167
+ # Base URL ν…ŒμŠ€νŠΈ
168
+ test_base_url()
169
+
170
+ # Gradio μΈν„°νŽ˜μ΄μŠ€ 생성
171
+ interface = gr.Interface(
172
+ fn=interface_function,
173
+ inputs=[
174
+ gr.Textbox(label="ν…μŠ€νŠΈ μž…λ ₯", placeholder="여기에 μŒμ„±μ„ ν•©μ„±ν•  ν…μŠ€νŠΈλ₯Ό μž…λ ₯ν•˜μ„Έμš”."),
175
+ gr.Dropdown(choices=actor_names, label="Actor 선택", interactive=True),
176
+ gr.Dropdown(choices=["en", "ko"], value="en", label="μ–Έμ–΄"),
177
+ gr.Slider(minimum=0.5, maximum=2.0, step=0.1, value=1.0, label="속도"),
178
+ gr.Slider(minimum=50, maximum=200, step=10, value=100, label="λ³Όλ₯¨"),
179
+ ],
180
+ outputs=[
181
+ gr.Textbox(label="κ²°κ³Ό λ©”μ‹œμ§€"),
182
+ gr.Audio(label="μƒμ„±λœ μŒμ„±"),
183
+ ],
184
+ title="μŒμ„± 생성 데λͺ¨",
185
+ description="쿼리 νŒŒλΌλ―Έν„°κ°€ 적용된 Actor 쑰회 ν›„ μŒμ„±μ„ μƒμ„±ν•©λ‹ˆλ‹€.",
186
  )
187
 
188
  if __name__ == "__main__":
189
+ interface.launch()