欢迎光临UUpython
最大、最新、最全的Python代码收集站

【web】在线文字转语音edge_tts web服务端

预览地址:https://tts.zhu.ee

1.服务端代码

from fastapi import FastAPI, Request, Form, File
from fastapi.responses import JSONResponse, FileResponse
from fastapi.templating import Jinja2Templates
import edge_tts  #pip install edge-tts
import asyncio
import hashlib
import datetime
import os
import tempfile
import pygame.mixer  # sudo apt-get install libsdl2-dev
import uvicorn

pygame.mixer.init()

app = FastAPI()
templates = Jinja2Templates(directory="templates")


async def my_function(text, output, voice, rate):
    volume = '+0%'
    tts = edge_tts.Communicate(text=text, voice=voice, rate=rate, volume=volume)
    await tts.save(output)


@app.get("/")
async def index(request: Request):
    return templates.TemplateResponse("index.html", {"request": request})


@app.post("/synthesize")
async def synthesize(request: Request):
    data = await request.json()
    text = data.get("text")
    voice = data.get("voice")
    rate = data.get("rate")
    output_dir = os.path.join(os.path.dirname(__file__), "mp3")
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    # 构造文件名
    now = datetime.datetime.now()
    filename_base = hashlib.md5((text[:5] + str(now.timestamp())).encode()).hexdigest()
    filename = os.path.join(output_dir, filename_base + ".mp3")

    with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3", dir=output_dir) as temp_file:
        temp_filename = temp_file.name
        await my_function(text, temp_filename, voice, rate)

    # 将临时文件转存为指定的输出文件
    os.rename(temp_filename, filename)

    # 返回包含下载链接的响应
    return JSONResponse(content={"message": "success", "download_link": f"/download?filename={filename}"})


@app.get("/download")
async def download(filename: str):
    file_path = os.path.join(app.root_path, filename)
    return FileResponse(path=file_path, filename=filename, media_type="application/octet-stream")


if __name__ == "__main__":
    uvicorn.run("main:app", host="127.0.0.1", port=8000, reload=True)
    # http://localhost:8000/

2.web界面代码(html+js)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>在线语音合成 Powered By ChatGPT</title>
<meta name="keywords" content="文字转语音,语音合成,微软语音合成,免费文本转语音,免费语音合成,在线文字转语音">
<meta name="description" content="在线免费语音合成,多种音源选择,支持语速调节!">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.3.0-alpha1/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
background-color: #f8f9fa;
}
.container {
max-width: 700px;
}
h1 {
font-size: 2.5rem;
font-weight: 700;
color: #333;
}
form {
background-color: #fff;
padding: 2rem;
border-radius: 12px;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
}
label {
font-size: 1rem;
font-weight: 700;
}
#synthesize-button {
background-color: #007bff;
border-color: #007bff;
}
#synthesize-button:hover {
background-color: #0069d9;
border-color: #0062cc;
}
#play-button {
background-color: #28a745;
border-color: #28a745;
}
#play-button:hover {
background-color: #218838;
border-color: #1e7e34;
}
</style>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
<div class="container">
<h1 class="text-center my-5">语音合成v1.0</h1>
<form id="synthesize-form">
<div class="mb-3">
<label for="text" class="form-label">请输入要转换为语音的文本:</label>
<textarea id="text" name="text" rows="4" class="form-control"></textarea>
</div>
<div class="mb-3">
<label for="voice" class="form-label">请选择要使用的语音角色:</label>
<select id="voice" name="voice" class="form-select">
<option value="zh-CN-XiaoxiaoNeural">小小-女</option>
<option value="zh-CN-XiaoyiNeural">小逸-女</option>
<option value="zh-CN-YunjianNeural">云剑-男</option>
<option value="zh-CN-YunxiNeural">云希-男</option>
<option value="zh-CN-YunxiaNeural">云夏-男</option>
<option value="zh-CN-YunyangNeural">云阳-男</option>
<option value="zh-CN-liaoning-XiaobeiNeural">辽宁小贝-女</option>
<option value="zh-CN-shaanxi-XiaoniNeural">陕西小妮-女</option>
<option value="zh-HK-HiuGaaiNeural">香港卓嘉-女</option>
<option value="zh-HK-HiuMaanNeural">香港卓萌-女</option>
<option value="zh-HK-WanLungNeural">香港万隆-男</option>
<option value="zh-TW-HsiaoChenNeural">台湾小陈-女</option>
<option value="zh-TW-HsiaoYuNeural">台湾小雨-女</option>
<option value="zh-TW-YunJheNeural">台湾云哲-男</option>
</select>
</div>
<div class="mb-3">
<label for="rate" class="form-label">调整语速:</label>
<select id="rate" name="rate" class="form-select">
<option value="-100%">-100</option>
<option value="-90%">-90</option>
<option value="-80%">-80</option>
<option value="-70%">-70</option>
<option value="-60%">-60</option>
<option value="-50%">-50</option>
<option value="-40%">-40</option>
<option value="-30%">-30</option>
<option value="-20%">-20</option>
<option value="-10%">-10</option>
<option value="+0%" selected>正常</option>
<option value="+10%" >+10</option>
<option value="+20%">+20</option>
<option value="+30%">+30</option>
<option value="+40%">+40</option>
<option value="+50%">+50</option>
<option value="+60%">+60</option>
<option value="+70%">+70</option>
<option value="+80%">+80</option>
<option value="+90%">+90</option>
<option value="+100%">+100</option>
</select>
</div>
<div class="text-center mb-3">
<button type="button" id="synthesize-button" class="btn btn-primary">合成音频</button>
</div>
<div class="text-center mb-3">
<button type="button" id="play-button" class="btn btn-success" style="display:none;">试听</button>
<div id="progress-container" class="progress mt-2" style="display:none; max-width: 200px; margin-left: auto; margin-right: auto;">
<div id="progress-bar" class="progress-bar progress-bar-striped" role="progressbar" style="width: 0%;" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<p id="download-link" class="d-inline-block mt-3" style="display:none;"></p>
</div>
</form>
</div>
</form>
</div>
<script>
var audio;
var isPlaying = false;
$("#synthesize-button").on("click", function(event) {
$(this).prop("disabled", true).text("生成中...");
requestSynthesis();
});
$("#play-button").on("click", function(event) {
if (isPlaying) {
audio.pause();
audio.currentTime = 0;
isPlaying = false;
$("#play-button").text("试听");
$("#progress-container").slideUp(); // Hide progress container
} else {
audio.play();
isPlaying = true;
$("#play-button").text("停止");
$("#progress-container").slideDown(); // Show progress container
 
// Update progress bar
audio.addEventListener("timeupdate", function () {
var progress = (audio.currentTime / audio.duration) * 100;
$("#progress-bar").css("width", progress + "%").attr("aria-valuenow", progress);
});
 
// Reset progress bar on ended
audio.addEventListener("ended", function () {
isPlaying = false;
$("#play-button").text("试听");
$("#progress-container").slideUp(); // Hide progress container
$("#progress-bar").css("width", 0 + "%").attr("aria-valuenow", 0);
});
}
});
 
function requestSynthesis() {
var form_data = {
'text': $("#text").val(),
'voice': $("#voice").val(),
'rate': $("#rate").val()
}
$.ajax({
url: "/synthesize",
type: "POST",
contentType: "application/json",
data: JSON.stringify(form_data),
success: function(response){
var download_link = response['download_link'];
$("#download-link").html( `<a href="${download_link}" class="btn btn-success" download>下载语音文件</a>` ).show();
audio = new Audio(download_link);
isPlaying = false;
$("#synthesize-button").prop("disabled", false).text("合成音频");
$("#play-button").show().text("试听");
audio.addEventListener("ended", function () {
isPlaying = false;
$("#play-button").text("试听");
});
}
});
}
</script>
</body>
<footer style="text-align: center; padding: 20px 0; font-size: 14px; font-weight: 400; color: #777; margin-top: 100px; border-top: 1px solid #e6e6e6;">
&#169; 2023年4月22日 由 <a href="https://www.openai.com/" style="color: #333; text-decoration: none;">ChatGPT</a> 生成
</footer>
</html>
赞(0) 打赏
未经允许不得转载:UUpython » 【web】在线文字转语音edge_tts web服务端
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!