mr-don88 commited on
Commit
ed7a892
·
verified ·
1 Parent(s): 3123380

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +38 -187
app.py CHANGED
@@ -1,199 +1,50 @@
1
- # -*- coding: utf-8 -*-
 
 
 
 
 
 
 
 
 
2
 
3
- import os, re, time, random
4
- import requests
5
- import gradio as gr
6
- from pydub import AudioSegment
7
- import natsort
8
 
9
- # ================== PATH SAFE ==================
10
- BASE_DIR = os.getcwd()
11
- VOICE_DIR = os.path.join(BASE_DIR, "voices")
12
- os.makedirs(VOICE_DIR, exist_ok=True)
13
 
14
- # ================== CORE ==================
15
- def check_api_key(api_key):
16
- try:
17
- r = requests.get(
18
- "https://api.elevenlabs.io/v1/user",
19
- headers={"xi-api-key": api_key},
20
- timeout=10
21
- )
22
- if r.status_code == 200:
23
- sub = r.json().get("subscription", {})
24
- return {
25
- "valid": True,
26
- "remaining": sub.get("character_limit", 0)
27
- - sub.get("character_count", 0)
28
- }
29
- return {"valid": False}
30
- except:
31
- return {"valid": False}
32
 
 
 
 
 
 
 
33
 
34
- def parse_text_blocks(text, max_len=200):
35
- blocks, cur = [], ""
36
- for s in re.split(r'(?<=[.!?])\s+', text):
37
- if len(cur) + len(s) <= max_len:
38
- cur += " " + s
39
- else:
40
- blocks.append(cur.strip())
41
- cur = s
42
- if cur:
43
- blocks.append(cur.strip())
44
- return blocks
45
 
 
 
 
 
 
46
 
47
- def estimate_credit(text):
48
- return len(text) + 50
49
 
 
 
 
50
 
51
- def generate_voice(text, api_key, voice_id, model_id,
52
- stability, similarity, style, speed, boost):
53
 
54
- time.sleep(random.uniform(1, 2))
 
 
55
 
56
- url = f"https://api.elevenlabs.io/v1/text-to-speech/{voice_id}"
57
- headers = {
58
- "xi-api-key": api_key,
59
- "Content-Type": "application/json"
60
- }
61
 
62
- payload = {
63
- "text": text,
64
- "model_id": model_id,
65
- "voice_settings": {
66
- "stability": stability,
67
- "similarity_boost": similarity,
68
- "style": style,
69
- "speed": speed,
70
- "use_speaker_boost": boost
71
- }
72
- }
73
-
74
- r = requests.post(url, headers=headers, json=payload, timeout=30)
75
- if r.status_code == 200:
76
- return r.content
77
- return None
78
-
79
-
80
- def merge_audio(fmt):
81
- files = natsort.natsorted([
82
- f for f in os.listdir(VOICE_DIR)
83
- if f.endswith("." + fmt.lower())
84
- ])
85
-
86
- if not files:
87
- return None
88
-
89
- combined = AudioSegment.from_file(os.path.join(VOICE_DIR, files[0]))
90
- for f in files[1:]:
91
- combined += AudioSegment.silent(500)
92
- combined += AudioSegment.from_file(os.path.join(VOICE_DIR, f))
93
-
94
- out_path = os.path.join(BASE_DIR, f"output_full.{fmt.lower()}")
95
- combined.export(out_path, format=fmt.lower())
96
- return out_path
97
-
98
-
99
- # ================== MAIN ==================
100
- def run_tts(api_keys_text, voice_id, text, model_id, fmt,
101
- stability, similarity, style, speed, boost):
102
-
103
- for f in os.listdir(VOICE_DIR):
104
- os.remove(os.path.join(VOICE_DIR, f))
105
-
106
- api_keys = [k.strip() for k in api_keys_text.splitlines() if k.strip()]
107
- valid_keys = []
108
-
109
- for k in api_keys:
110
- info = check_api_key(k)
111
- if info.get("valid") and info["remaining"] > 500:
112
- valid_keys.append([k, info["remaining"]])
113
-
114
- if not valid_keys:
115
- return "❌ Không có API key hợp lệ", None
116
-
117
- blocks = parse_text_blocks(text)
118
- key_idx = 0
119
-
120
- for i, block in enumerate(blocks):
121
- success = False
122
-
123
- while valid_keys:
124
- key, remain = valid_keys[key_idx]
125
- need = estimate_credit(block)
126
-
127
- if remain < need:
128
- valid_keys.pop(key_idx)
129
- continue
130
-
131
- audio = generate_voice(
132
- block, key, voice_id, model_id,
133
- stability, similarity, style, speed, boost
134
- )
135
-
136
- if audio:
137
- path = os.path.join(
138
- VOICE_DIR, f"voice_{i+1:03d}.{fmt.lower()}"
139
- )
140
- with open(path, "wb") as f:
141
- f.write(audio)
142
- valid_keys[key_idx][1] -= need
143
- success = True
144
- break
145
- else:
146
- valid_keys.pop(key_idx)
147
-
148
- if not success:
149
- return "❌ Hết API key khi đang chạy", None
150
-
151
- merged = merge_audio(fmt)
152
- return "✅ Hoàn tất", merged
153
-
154
-
155
- # ================== UI ==================
156
- with gr.Blocks() as demo:
157
- gr.Markdown("## 🔊 ElevenLabs TTS – Hugging Face Stable")
158
-
159
- api_keys = gr.Textbox(label="API Keys (mỗi dòng 1 key)", lines=4)
160
- voice_id = gr.Textbox(label="Voice ID")
161
- text = gr.Textbox(label="Text", lines=6)
162
-
163
- model = gr.Dropdown(
164
- choices=[
165
- ("Turbo v2.5", "eleven_turbo_v2_5"),
166
- ("Flash v2.5", "eleven_flash_v2_5"),
167
- ("Multilingual v2", "eleven_multilingual_v2"),
168
- ],
169
- value="eleven_multilingual_v2",
170
- label="Model"
171
- )
172
-
173
- fmt = gr.Dropdown(["MP3", "WAV"], value="MP3", label="Format")
174
-
175
- stability = gr.Slider(0, 1, 0.9, label="Stability")
176
- similarity = gr.Slider(0, 1, 0.5, label="Similarity")
177
- style = gr.Slider(0, 1, 0.4, label="Style")
178
- speed = gr.Slider(0.7, 1.2, 0.81, label="Speed")
179
- boost = gr.Checkbox(True, label="Speaker Boost")
180
-
181
- run_btn = gr.Button("🎧 Tạo giọng nói")
182
- status = gr.Textbox(label="Status")
183
- output_audio = gr.Audio(type="filepath", label="Output")
184
-
185
- run_btn.click(
186
- run_tts,
187
- inputs=[
188
- api_keys, voice_id, text, model, fmt,
189
- stability, similarity, style, speed, boost
190
- ],
191
- outputs=[status, output_audio]
192
- )
193
-
194
- # ⚠️ DÒNG QUAN TRỌNG NHẤT CHO HUGGING FACE
195
- demo.launch(
196
- server_name="0.0.0.0",
197
- server_port=7860,
198
- show_error=True
199
- )
 
1
+ ---
2
+ title: ElevenLabs TTS Pro
3
+ emoji: 🎤
4
+ colorFrom: blue
5
+ colorTo: green
6
+ sdk: gradio
7
+ sdk_version: 4.0.0
8
+ app_file: app.py
9
+ pinned: false
10
+ ---
11
 
12
+ # 🎤 ElevenLabs TTS Pro
 
 
 
 
13
 
14
+ Công cụ chuyển văn bản thành giọng nói chuyên nghiệp sử dụng API của ElevenLabs.
 
 
 
15
 
16
+ ## 🚀 Tính năng
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
+ - 🤖 Hỗ trợ nhiều API keys của ElevenLabs
19
+ - 🎭 Tạo giọng nói với nhiều thông số tùy chỉnh
20
+ - 📝 Hỗ trợ văn bản dài, tự động chia đoạn
21
+ - 💾 Xuất file audio (MP3, WAV, OGG, FLAC)
22
+ - 📄 Tạo file phụ đề SRT tự động
23
+ - 📁 Tải cấu hình từ file (TXT, JSON, ENV)
24
 
25
+ ## 🔧 Cách sử dụng
 
 
 
 
 
 
 
 
 
 
26
 
27
+ 1. **Nhập API Keys**: Lấy từ [ElevenLabs](https://elevenlabs.io/) và nhập vào ô API Keys
28
+ 2. **Nhập Voice ID**: Voice ID từ ElevenLabs (VD: `21m00Tcm4TlvDq8ikWAM`)
29
+ 3. **Nhập văn bản**: Văn bản cần chuyển thành giọng nói
30
+ 4. **Tùy chỉnh thông số**: Stability, Similarity, Style, Speed
31
+ 5. **Nhấn "Bắt đầu Tạo Giọng nói"**
32
 
33
+ ## 📁 Định dạng file hỗ trợ
 
34
 
35
+ - **API Keys**: `.txt`, `.json`, `.env`
36
+ - **Voice IDs**: `.txt`, `.json`
37
+ - **Văn bản**: `.txt`, `.json`
38
 
39
+ ## ⚠️ Lưu ý
 
40
 
41
+ - Cần có API key hợp lệ từ ElevenLabs
42
+ - Giới hạn ký tự theo gói subscription của bạn
43
+ - File tạo ra sẽ được lưu tạm thời và tự động xóa sau phiên làm việc
44
 
45
+ ## 🛠️ Công nghệ sử dụng
 
 
 
 
46
 
47
+ - Gradio: Giao diện web
48
+ - ElevenLabs API: TTS engine
49
+ - Pydub: Xử lý audio
50
+ - Python 3.8+