Update app.py
Browse files
app.py
CHANGED
|
@@ -3,7 +3,6 @@ import edge_tts
|
|
| 3 |
import gradio as gr
|
| 4 |
import os
|
| 5 |
from datetime import datetime
|
| 6 |
-
from pydub import AudioSegment
|
| 7 |
|
| 8 |
AUDIO_DIR = "saved_audios"
|
| 9 |
os.makedirs(AUDIO_DIR, exist_ok=True)
|
|
@@ -12,16 +11,17 @@ def generate_unique_filename(folder, prefix="audio", ext="mp3"):
|
|
| 12 |
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S_%f")
|
| 13 |
return os.path.join(folder, f"{prefix}_{timestamp}.{ext}")
|
| 14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
async def generate_speech(text, voice, rate, pitch, folder=AUDIO_DIR):
|
| 16 |
output_file = generate_unique_filename(folder)
|
| 17 |
communicate = edge_tts.Communicate(text, voice, rate=rate, pitch=pitch)
|
| 18 |
await communicate.save(output_file)
|
| 19 |
return output_file
|
| 20 |
|
| 21 |
-
async def get_voices():
|
| 22 |
-
voices = await edge_tts.list_voices()
|
| 23 |
-
return [voice["ShortName"] for voice in voices]
|
| 24 |
-
|
| 25 |
def list_saved_audios():
|
| 26 |
files = sorted(os.listdir(AUDIO_DIR), reverse=True)
|
| 27 |
return [os.path.join(AUDIO_DIR, f) for f in files if f.endswith(".mp3")]
|
|
@@ -38,6 +38,10 @@ def play_saved_audio(audio_file):
|
|
| 38 |
def clear_textbox():
|
| 39 |
return ""
|
| 40 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
| 42 |
gr.Markdown("## 🎙️ Edge TTS 語音合成工具\n\n- 支援語音合成、語音檔自動儲存與播放\n- 介面簡潔、操作直覺")
|
| 43 |
|
|
@@ -45,7 +49,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
| 45 |
with gr.Row():
|
| 46 |
text_input = gr.Textbox(lines=5, label="輸入文本")
|
| 47 |
clear_btn = gr.Button("清空")
|
| 48 |
-
voice_input = gr.Dropdown(
|
| 49 |
rate_input = gr.Slider(-50, 50, value=0, step=1, label="語速調整 (%)")
|
| 50 |
pitch_input = gr.Slider(-50, 50, value=0, step=1, label="音高調整 (Hz)")
|
| 51 |
tts_btn = gr.Button("生成語音")
|
|
@@ -62,10 +66,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
| 62 |
saved_audio_output = gr.Audio(type="filepath", label="播放已儲存語音")
|
| 63 |
audio_files.change(fn=play_saved_audio, inputs=audio_files, outputs=saved_audio_output)
|
| 64 |
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
voice_input.choices = voices
|
| 68 |
-
voice_input.value = "zh-CN-XiaoxiaoNeural" if "zh-CN-XiaoxiaoNeural" in voices else voices[0]
|
| 69 |
-
asyncio.get_event_loop().run_until_complete(init_voices())
|
| 70 |
|
| 71 |
demo.launch()
|
|
|
|
| 3 |
import gradio as gr
|
| 4 |
import os
|
| 5 |
from datetime import datetime
|
|
|
|
| 6 |
|
| 7 |
AUDIO_DIR = "saved_audios"
|
| 8 |
os.makedirs(AUDIO_DIR, exist_ok=True)
|
|
|
|
| 11 |
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S_%f")
|
| 12 |
return os.path.join(folder, f"{prefix}_{timestamp}.{ext}")
|
| 13 |
|
| 14 |
+
async def get_voices():
|
| 15 |
+
# 取得 Edge TTS 可用語音清單
|
| 16 |
+
voices = await edge_tts.list_voices()
|
| 17 |
+
return [voice["ShortName"] for voice in voices]
|
| 18 |
+
|
| 19 |
async def generate_speech(text, voice, rate, pitch, folder=AUDIO_DIR):
|
| 20 |
output_file = generate_unique_filename(folder)
|
| 21 |
communicate = edge_tts.Communicate(text, voice, rate=rate, pitch=pitch)
|
| 22 |
await communicate.save(output_file)
|
| 23 |
return output_file
|
| 24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
def list_saved_audios():
|
| 26 |
files = sorted(os.listdir(AUDIO_DIR), reverse=True)
|
| 27 |
return [os.path.join(AUDIO_DIR, f) for f in files if f.endswith(".mp3")]
|
|
|
|
| 38 |
def clear_textbox():
|
| 39 |
return ""
|
| 40 |
|
| 41 |
+
# 先同步取得語音清單,避免 async 問題
|
| 42 |
+
voices = asyncio.run(get_voices())
|
| 43 |
+
default_voice = "zh-CN-XiaoxiaoNeural" if "zh-CN-XiaoxiaoNeural" in voices else voices[0]
|
| 44 |
+
|
| 45 |
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
| 46 |
gr.Markdown("## 🎙️ Edge TTS 語音合成工具\n\n- 支援語音合成、語音檔自動儲存與播放\n- 介面簡潔、操作直覺")
|
| 47 |
|
|
|
|
| 49 |
with gr.Row():
|
| 50 |
text_input = gr.Textbox(lines=5, label="輸入文本")
|
| 51 |
clear_btn = gr.Button("清空")
|
| 52 |
+
voice_input = gr.Dropdown(voices, value=default_voice, label="選擇語音")
|
| 53 |
rate_input = gr.Slider(-50, 50, value=0, step=1, label="語速調整 (%)")
|
| 54 |
pitch_input = gr.Slider(-50, 50, value=0, step=1, label="音高調整 (Hz)")
|
| 55 |
tts_btn = gr.Button("生成語音")
|
|
|
|
| 66 |
saved_audio_output = gr.Audio(type="filepath", label="播放已儲存語音")
|
| 67 |
audio_files.change(fn=play_saved_audio, inputs=audio_files, outputs=saved_audio_output)
|
| 68 |
|
| 69 |
+
# 若要每次開啟都刷新語音檔案清單,可加下列一行
|
| 70 |
+
# demo.load(lambda: gr.Dropdown.update(choices=list_saved_audios()), None, audio_files)
|
|
|
|
|
|
|
|
|
|
| 71 |
|
| 72 |
demo.launch()
|