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