#1475 项目运行后打开浏览器http://127.0.0.1:9090/显示127.0.0.1 拒绝了我们的连接请求。 请试试以下办法: 检查网络连接 检查代理服务器和防火墙 ERR_CONNECTION_REFUSED

54.178* Posted at: 2 hours ago 👁12

项目运行后打开浏览器http://127.0.0.1:9090/显示127.0.0.1 拒绝了我们的连接请求。 请试试以下办法: 检查网络连接 检查代理服务器和防火墙 ERR_CONNECTION_REFUSED是什么原因?如何处理?脚本如下:# /// script

requires-python = "==3.10.*"

dependencies = [

"flask",

"edge-tts",

"waitress"

]

///

import json,os
from pathlib import Path
import asyncio
from datetime import datetime
from io import BytesIO
import webbrowser
from threading import Timer
from flask import Flask, render_template, request, send_file, jsonify
from waitress import serve
import edge_tts

app = Flask(__name__,template_folder='.')
ROOT=Path(os.getcwd()).as_posix()

try:

with open(f'{ROOT}/edge_tts.json', 'r', encoding='utf-8') as f:
    voices_data = json.load(f)

except FileNotFoundError:

print("致命错误: 未找到 edge_tts.json。")
print("请确保 edge_tts.json 文件与 app.py 在同一目录下。")
voices_data = {}

except json.JSONDecodeError:

print("致命错误: 无法解析 edge_tts.json。")
print("请确保它是一个有效的 JSON 文件。")
voices_data = {}

@app.route('/')
def index():

"""
渲染主 HTML 页面,并将语音数据传递给它。
'voices_data' 将在模板中被 JavaScript 使用。
"""
return render_template('index.html', voices_data=voices_data)

async def generate_audio(text, voice, rate, volume, pitch):

"""
一个异步函数,使用 edge-tts 库从文本生成音频,
并将其作为内存中的字节流返回。
"""
communicate = edge_tts.Communicate(text=text, voice=voice, rate=rate, volume=volume, pitch=pitch)

audio_buffer = BytesIO()

async for chunk in communicate.stream():
    if chunk["type"] == "audio":
        audio_buffer.write(chunk["data"])

audio_buffer.seek(0)
return audio_buffer

@app.route('/api/tts', methods=['POST'])
def tts_api():

"""
处理来自前端的 POST 请求,生成音频,
并将其作为 MP3 文件发送回去。
"""
data = request.get_json()
if not data:
    return jsonify({"error": "无效的 JSON 请求"}), 400

text = data.get('text')
voice = data.get('voice')
rate = data.get('rate', '+0%')
volume = data.get('volume', '+0%')
pitch = data.get('pitch', '+0Hz')

if not text or not voice:
    return jsonify({"error": "请求中缺少 'text' 或 'voice'"}), 400

try:
    audio_buffer = asyncio.run(generate_audio(text, voice, rate, volume, pitch))

    filename = datetime.now().strftime("%Y%m%d%H%M%S") + ".mp3"

    return send_file(
        audio_buffer,
        mimetype='audio/mpeg',
        as_attachment=True,
        download_name=filename
    )
except Exception as e:
    print(f"TTS 生成过程中发生错误: {e}")
    return jsonify({"error": "由于内部服务器错误,生成音频失败。"}), 500

def open_browser():

"""
在默认 Web 浏览器中打开应用。
"""
webbrowser.open_new("http://127.0.0.1:9090")

if name == '__main__':

HOST = '127.0.0.1'
PORT = 9090

print(f"服务器已启动,访问地址: http://{HOST}:{PORT}")
print("按 Ctrl+C 停止服务器")

Timer(1, open_browser).start()

serve(app, host='0.0.0.0', port=PORT)

7 Replies

您提供的脚本是一个使用 Flask 和 Waitress 搭建的本地 TTS 服务,但访问 http://127.0.0.1:9090 被拒绝。这通常由以下几个原因导致:

  1. 脚本未成功运行或已退出: 检查命令行窗口是否仍在运行,并且没有因为 edge_tts.json 文件缺失或格式错误而提前终止。请确保该文件存在于脚本同目录下。
  2. 端口冲突: 端口 9090 可能已被其他程序占用。请尝试修改脚本末尾的 PORT 变量为一个不同的端口(例如 8080),然后重新运行脚本。
  3. 防火墙阻止: 系统防火墙可能阻止了 Python 或该脚本的网络访问。请暂时禁用防火墙测试,或在防火墙设置中为 Python 添加入站规则。
  4. Waitress 绑定地址问题: 脚本中 serve(app, host='0.0.0.0', port=PORT) 绑定的是 0.0.0.0,这意味着它接受所有网络接口的连接。您应该能通过 http://localhost:9090http://[您的本地IP]:9090 访问。如果仅 127.0.0.1 无法访问,请尝试改用 localhost

处理步骤:

  1. 首先,确认脚本正在运行且命令行窗口没有报错退出。
  2. 尝试在浏览器中访问 http://localhost:9090
  3. 如果仍不行,将脚本中的 PORT = 9090 改为 PORT = 8080,然后重新运行并访问 http://127.0.0.1:8080
  4. 检查并处理防火墙设置。

如果以上步骤均无效,请提供运行脚本时命令行窗口输出的完整信息。

控制台有下面的错误信息:..\lib\site-packages\waitress\wasyncore.py", line 374, in bind

return self.socket.bind(addr)

PermissionError: [WinError 10013] 以一种访问权限不允许的方式做了一个访问套接字的尝试。

这个错误 PermissionError: [WinError 10013] 表示端口 9090 被系统或其他应用程序占用,或者 Python 没有权限绑定该端口。

解决方案如下:

  1. 更换端口(最直接有效的方法)
    修改您脚本末尾的 PORT 变量,将其从 9090 改为一个未被占用的端口,例如 808050007860

    # 在脚本末尾找到这行并修改
    PORT = 8080  # 将 9090 改为 8080

    保存后重新运行脚本,然后访问新的地址:http://127.0.0.1:8080

  2. 以管理员身份运行(如果必须使用特定端口)
    如果您必须使用 9090 端口,可以尝试以管理员身份打开命令行或 PowerShell,然后在此窗口中运行您的 Python 脚本。这会赋予程序绑定系统端口的权限。

首选方案是第1种,更换端口通常能立即解决问题,且无需提升权限。

继续,这个脚本的tts是否需要调用微软的服务有速度限制?

是的,脚本使用的 edge-tts 库调用的是微软的 Edge 浏览器在线 TTS 服务,该服务存在请求频率限制。

主要限制表现:

  1. 请求频率限制:短时间内发送过多请求会被服务器暂时拒绝,返回错误或空音频。
  2. 并发连接限制:同时发起的连接数有限制。
  3. 文本长度限制:单次请求的文本有最大字符数限制(通常约为 1000-2000 字符)。

在您的脚本中规避限制的方法:

  1. 降低并发:您的脚本是单线程处理 /api/tts 请求,这本身已经避免了并发问题。
  2. 添加请求间隔:可以在 tts_api() 路由处理函数中,在处理请求前添加一个短暂的延迟(例如 time.sleep(0.5)),以降低请求频率。
  3. 客户端控制:在前端页面(index.html)中,可以添加限制,防止用户过快连续点击“生成”按钮。

建议的优化修改:
在您的 tts_api() 函数开头添加延迟(需要先 import time):

@app.route('/api/tts', methods=['POST'])
def tts_api():
    # 添加延迟,降低请求频率
    time.sleep(0.5)  # 延迟 0.5 秒
    
    data = request.get_json()
    # ... 其余代码不变 ...

这样可以有效减少因频率过高导致的失败。如果仍然遇到限制,可以适当增加延迟时间。

继续,能把脚本修改为多线程并发的,但是间隔时间可以延长到1-2秒的么?

您的脚本已经是多线程的,因为 Waitress 是一个多线程 WSGI 服务器。您需要的是在服务器端添加频率限制,而不是修改为多线程并发。以下是修改方案:

修改后的脚本(添加了频率限制):

# /// script
requires-python = "==3.10.*"
dependencies = [
    "flask",
    "edge-tts", 
    "waitress",
    "flask-limiter"  # 新增依赖
]
///

import json, os, time
from pathlib import Path
import asyncio
from datetime import datetime
from io import BytesIO
import webbrowser
from threading import Timer
from flask import Flask, render_template, request, send_file, jsonify
from waitress import serve
import edge_tts
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address

app = Flask(__name__, template_folder='.')
ROOT = Path(os.getcwd()).as_posix()

# 初始化频率限制器
limiter = Limiter(
    app=app,
    key_func=get_remote_address,
    default_limits=["2 per second"]  # 限制每秒最多2个请求
)

try:
    with open(f'{ROOT}/edge_tts.json', 'r', encoding='utf-8') as f:
        voices_data = json.load(f)
except FileNotFoundError:
    print("致命错误: 未找到 edge_tts.json。")
    print("请确保 edge_tts.json 文件与 app.py 在同一目录下。")
    voices_data = {}
except json.JSONDecodeError:
    print("致命错误: 无法解析 edge_tts.json。")
    print("请确保它是一个有效的 JSON 文件。")
    voices_data = {}

@app.route('/')
def index():
    return render_template('index.html', voices_data=voices_data)

async def generate_audio(text, voice, rate, volume, pitch):
    communicate = edge_tts.Communicate(text=text, voice=voice, rate=rate, volume=volume, pitch=pitch)
    audio_buffer = BytesIO()
    
    async for chunk in communicate.stream():
        if chunk["type"] == "audio":
            audio_buffer.write(chunk["data"])
    
    audio_buffer.seek(0)
    return audio_buffer

@app.route('/api/tts', methods=['POST'])
@limiter.limit("1 per 2 seconds")  # 限制每2秒最多1个请求
def tts_api():
    data = request.get_json()
    if not data:
        return jsonify({"error": "无效的 JSON 请求"}), 400

    text = data.get('text')
    voice = data.get('voice')
    rate = data.get('rate', '+0%')
    volume = data.get('volume', '+0%')
    pitch = data.get('pitch', '+0Hz')

    if not text or not voice:
        return jsonify({"error": "请求中缺少 'text' 或 'voice'"}), 400

    try:
        audio_buffer = asyncio.run(generate_audio(text, voice, rate, volume, pitch))
        filename = datetime.now().strftime("%Y%m%d%H%M%S") + ".mp3"
        
        return send_file(
            audio_buffer,
            mimetype='audio/mpeg',
            as_attachment=True,
            download_name=filename
        )
    except Exception as e:
        print(f"TTS 生成过程中发生错误: {e}")
        return jsonify({"error": "由于内部服务器错误,生成音频失败。"}), 500

def open_browser():
    webbrowser.open_new("http://127.0.0.1:9090")

if __name__ == '__main__':
    HOST = '127.0.0.1'
    PORT = 8080  # 建议使用8080避免权限问题
    
    print(f"服务器已启动,访问地址: http://{HOST}:{PORT}")
    print("按 Ctrl+C 停止服务器")
    
    Timer(1, open_browser).start()
    serve(app, host='0.0.0.0', port=PORT)

主要改进:

  1. 添加了 Flask-Limiter:使用 @limiter.limit("1 per 2 seconds") 装饰器限制每个 IP 地址每 2 秒只能发送 1 个 TTS 请求
  2. 全局限制:设置 default_limits=["2 per second"] 作为额外的保护层
  3. 修改端口:将端口改为 8080 以避免权限问题
  4. 保持多线程:Waitress 默认就是多线程的,可以同时处理多个页面请求

安装新依赖:

pip install flask-limiter

这样修改后,您的服务可以同时处理多个用户的页面访问,但对 TTS API 的调用会受到严格的频率限制,有效避免微软服务的限制。

Post Your Reply
Open source and free maintenance is not easy. If this project is helpful to you, please consider making a small donation to help the project continue to maintain and update.

Donate: https://ko-fi.com/jianchang512

Trending Questions