mr-don88 commited on
Commit
8d63a70
·
verified ·
1 Parent(s): ce75e96

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +127 -49
app.py CHANGED
@@ -1,35 +1,47 @@
1
- import requests
2
- import random
3
- import time
 
4
 
 
5
  def check_api_key(api_key):
6
  try:
7
- res = requests.get(
8
  "https://api.elevenlabs.io/v1/user",
9
  headers={"xi-api-key": api_key},
10
  timeout=10
11
  )
12
- if res.status_code == 200:
13
- sub = res.json().get("subscription", {})
14
- remaining = sub.get("character_limit", 0) - sub.get("character_count", 0)
15
- if remaining > 600:
16
- return {"valid": True, "remaining": remaining}
17
- else:
18
- return {"valid": False, "error": "API key hết credit."}
 
 
 
 
 
 
 
19
  else:
20
- return {"valid": False, "error": f"Lỗi kết nối: {res.status_code}"}
21
- except Exception as e:
22
- return {"valid": False, "error": str(e)}
 
 
23
 
24
- def tts(text, api_key, voice_id, model):
25
- time.sleep(random.uniform(0.8, 1.5)) # Delay random để tránh lỗi rate-limit
26
 
 
 
 
27
  r = requests.post(
28
  f"https://api.elevenlabs.io/v1/text-to-speech/{voice_id}",
29
  headers={
30
  "xi-api-key": api_key,
31
  "Content-Type": "application/json",
32
- "Accept": "audio/mpeg"
33
  },
34
  json={
35
  "text": text,
@@ -44,40 +56,106 @@ def tts(text, api_key, voice_id, model):
44
  },
45
  timeout=60
46
  )
 
 
 
47
 
48
- if r.status_code == 200:
49
- if r.headers.get("content-type", "").startswith("audio"):
50
- return r.content
51
- else:
52
- print("❌ Không có audio trong phản hồi")
53
- else:
54
- print(f"❌ Lỗi API: {r.status_code}")
55
- print(f"Chi tiết lỗi: {r.text}")
56
 
57
- return None
 
 
 
 
 
 
 
 
 
58
 
59
- def run_tool(api_keys_content, text, voice_id, model_id):
60
- api_keys = [line.strip() for line in api_keys_content.decode().splitlines() if line.strip()]
61
- valid_keys = []
62
 
63
- for key in api_keys:
64
- key_info = check_api_key(key)
65
- if key_info["valid"]:
66
- valid_keys.append(key)
67
- print(f"✅ Key {key[:6]}... hợp lệ, còn {key_info['remaining']} tín dụng.")
68
- else:
69
- print(f"❌ Key {key[:6]}... không hợp lệ: {key_info.get('error', 'Không rõ lý do')}")
70
-
71
- if not valid_keys:
72
- print("❌ Không có API key hợp lệ.")
73
- return
74
-
75
- for key in valid_keys:
76
- audio = tts(text, key, voice_id, model_id)
77
- if audio:
78
- print("🎧 Tạo giọng nói thành công.")
79
- return audio
 
 
 
 
 
 
 
 
 
 
 
 
80
  else:
81
- print(f" Không thể tạo giọng nói với key {key[:6]}...")
82
-
83
- print("❌ Không API key nào tạo được audio")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ import os, re, time, random, zipfile, requests, natsort
3
+ import gradio as gr
4
+ from pydub import AudioSegment
5
 
6
+ # ================= API CHECK =================
7
  def check_api_key(api_key):
8
  try:
9
+ r = requests.get(
10
  "https://api.elevenlabs.io/v1/user",
11
  headers={"xi-api-key": api_key},
12
  timeout=10
13
  )
14
+ if r.status_code != 200:
15
+ return None
16
+ sub = r.json().get("subscription", {})
17
+ return sub.get("character_limit", 0) - sub.get("character_count", 0)
18
+ except:
19
+ return None
20
+
21
+
22
+ # ================= TEXT =================
23
+ def split_text(text, max_len=200):
24
+ out, cur = [], ""
25
+ for s in re.split(r'(?<=[.!?])\s+', text):
26
+ if len(cur) + len(s) <= max_len:
27
+ cur += " " + s
28
  else:
29
+ out.append(cur.strip())
30
+ cur = s
31
+ if cur:
32
+ out.append(cur.strip())
33
+ return out
34
 
 
 
35
 
36
+ # ================= TTS (FIX QUAN TRỌNG) =================
37
+ def tts(text, api_key, voice_id, model):
38
+ time.sleep(random.uniform(0.8, 1.5))
39
  r = requests.post(
40
  f"https://api.elevenlabs.io/v1/text-to-speech/{voice_id}",
41
  headers={
42
  "xi-api-key": api_key,
43
  "Content-Type": "application/json",
44
+ "Accept": "audio/mpeg" # 🔥 BẮT BUỘC
45
  },
46
  json={
47
  "text": text,
 
56
  },
57
  timeout=60
58
  )
59
+ if r.status_code == 200 and len(r.content) > 1000:
60
+ return r.content
61
+ return None
62
 
 
 
 
 
 
 
 
 
63
 
64
+ # ================= AUDIO + SRT =================
65
+ def merge_audio(folder, fmt):
66
+ files = natsort.natsorted(f for f in os.listdir(folder) if f.endswith(fmt))
67
+ audio = AudioSegment.from_file(os.path.join(folder, files[0]))
68
+ for f in files[1:]:
69
+ audio += AudioSegment.silent(500)
70
+ audio += AudioSegment.from_file(os.path.join(folder, f))
71
+ out = f"output_full.{fmt}"
72
+ audio.export(out, format=fmt)
73
+ return out
74
 
 
 
 
75
 
76
+ def create_srt(folder, texts):
77
+ t, lines = 0, []
78
+ files = natsort.natsorted(f for f in os.listdir(folder) if f.startswith("voice_"))
79
+ for i, (f, txt) in enumerate(zip(files, texts), 1):
80
+ a = AudioSegment.from_file(os.path.join(folder, f))
81
+ lines += [
82
+ str(i),
83
+ f"00:00:{t//1000:02},{t%1000:03} --> 00:00:{(t+len(a))//1000:02},{(t+len(a))%1000:03}",
84
+ txt, ""
85
+ ]
86
+ t += len(a) + 500
87
+ with open(os.path.join(folder, "output_full.srt"), "w", encoding="utf-8") as f:
88
+ f.write("\n".join(lines))
89
+
90
+
91
+ # ================= RUN =================
92
+ def run(api_text, api_file, voice_id, text, model, fmt):
93
+ keys = api_file.decode().splitlines() if api_file else api_text.splitlines()
94
+ keys = [k.strip() for k in keys if k.strip()]
95
+
96
+ table = "| API KEY | CREDIT |\n|---|---|\n"
97
+ valid = []
98
+
99
+ for k in keys:
100
+ rem = check_api_key(k)
101
+ show = f"{k[:6]}...{k[-4:]}"
102
+ if rem and rem > 600:
103
+ valid.append(k)
104
+ table += f"| {show} | {rem} |\n"
105
  else:
106
+ table += f"| {show} | |\n"
107
+
108
+ if not valid:
109
+ return "❌ Không có API key >600", None, None, table
110
+
111
+ texts = split_text(text)
112
+ os.makedirs("voices", exist_ok=True)
113
+ for f in os.listdir("voices"):
114
+ os.remove(os.path.join("voices", f))
115
+
116
+ for i, t in enumerate(texts):
117
+ success = False
118
+ for key in valid:
119
+ audio = tts(t, key, voice_id, model)
120
+ if audio:
121
+ with open(f"voices/voice_{i+1:03d}.{fmt}", "wb") as f:
122
+ f.write(audio)
123
+ success = True
124
+ break
125
+ if not success:
126
+ return "❌ Không API key nào tạo được audio", None, None, table
127
+
128
+ merged = merge_audio("voices", fmt)
129
+ create_srt("voices", texts)
130
+
131
+ zipf = "output.zip"
132
+ with zipfile.ZipFile(zipf, "w") as z:
133
+ for f in os.listdir("voices"):
134
+ z.write(os.path.join("voices", f), f)
135
+ z.write(merged)
136
+
137
+ return "✅ HOÀN TẤT", merged, zipf, table
138
+
139
+
140
+ # ================= UI =================
141
+ with gr.Blocks() as app:
142
+ gr.Markdown("## 🔊 ElevenLabs TTS – FIX CHUẨN HF")
143
+
144
+ api_text = gr.Textbox(lines=4, label="API key")
145
+ api_file = gr.File(type="binary", label="Upload API file")
146
+ voice_id = gr.Textbox(label="Voice ID")
147
+ text = gr.Textbox(lines=6, label="Text")
148
+
149
+ model = gr.Dropdown(["eleven_multilingual_v2"], value="eleven_multilingual_v2")
150
+ fmt = gr.Dropdown(["mp3", "wav"], value="mp3")
151
+
152
+ btn = gr.Button("🎧 TẠO GIỌNG")
153
+ status = gr.Textbox()
154
+ audio = gr.Audio(type="filepath")
155
+ zipf = gr.File()
156
+ table = gr.Markdown()
157
+
158
+ btn.click(run, [api_text, api_file, voice_id, text, model, fmt],
159
+ [status, audio, zipf, table])
160
+
161
+ app.launch()