HTML 版本

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>文本转语音并播放</title>
</head>
<body>
    <h1>文本转语音并播放</h1>

    <label for="textInput">请输入文本:</label><br>
    <textarea id="textInput" rows="4" cols="50"></textarea><br><br>

    <label for="filterChinese">只显示中文语音?</label>
    <input type="checkbox" id="filterChinese" checked><br><br>

    <label for="voiceSelect">选择语音(音色):</label>
    <select id="voiceSelect"></select><br><br>

    <button id="startButton">开始朗读</button>
    <button id="stopButton">停止朗读</button>

    <script>
        // 获取可用的语音并填充选择框
        function populateVoiceList() {
            const voices = speechSynthesis.getVoices();
            const voiceSelect = document.getElementById('voiceSelect');
            const filterChinese = document.getElementById('filterChinese').checked;
            voiceSelect.innerHTML = ''; // 清空现有选项

            // 支持所有语音(更多音色),或可选过滤中文
            let filteredVoices = voices;
            if (filterChinese) {
                filteredVoices = voices.filter(voice => voice.lang.startsWith('zh-')); // 支持 zh-CN, zh-TW 等
            }

            console.log('可用语音列表:', filteredVoices); // 调试:打印到控制台

            if (filteredVoices.length === 0) {
                // 如果没有语音,显示提示
                const option = document.createElement('option');
                option.textContent = '无可用语音(请安装TTS引擎)';
                option.disabled = true;
                voiceSelect.appendChild(option);
                alert('未检测到任何可用语音。请确保系统已安装TTS语音包,并在浏览器中刷新页面。');
                return;
            }

            // 将语音填充到下拉框
            filteredVoices.forEach((voice) => {
                const option = document.createElement('option');
                option.value = voice.name;
                option.textContent = `${voice.name} (${voice.lang})`; // 显示名称和语言,便于选择
                voiceSelect.appendChild(option);
            });
        }

        // 创建朗读函数
        function speak(text, selectedVoice) {
            const utterance = new SpeechSynthesisUtterance(text);
            utterance.voice = selectedVoice; // 设置选择的音色
            utterance.lang = selectedVoice ? selectedVoice.lang : 'zh-CN'; // 自动匹配语言

            // 启动语音合成
            speechSynthesis.speak(utterance);
        }

        // 执行朗读
        document.getElementById('startButton').addEventListener('click', () => {
            const textInput = document.getElementById('textInput').value.trim();
            const selectedVoiceName = document.getElementById('voiceSelect').value;
            const voices = speechSynthesis.getVoices();
            const selectedVoice = voices.find(voice => voice.name === selectedVoiceName);

            if (!textInput) {
                alert('请输入文本');
                return;
            }
            if (!selectedVoice) {
                alert('请选择一个有效语音');
                return;
            }

            speak(textInput, selectedVoice);
        });

        // 停止朗读
        document.getElementById('stopButton').addEventListener('click', () => {
            speechSynthesis.cancel(); // 停止当前语音播放
        });

        // 复选框变化时重新填充语音列表
        document.getElementById('filterChinese').addEventListener('change', populateVoiceList);

        // 初始化并填充可用的语音列表
        populateVoiceList();

        // 在语音列表加载完后,重新填充语音选择框
        if (speechSynthesis.onvoiceschanged !== undefined) {
            speechSynthesis.onvoiceschanged = populateVoiceList;
        }
    </script>
</body>
</html>

python 批量生成

import pyttsx3
import os
import sys

def populate_voice_list():
    engine = pyttsx3.init()
    voices = engine.getProperty('voices')
    # 过滤中文语音(假设语言代码包含 'zh')
    chinese_voices = [voice for voice in voices if any('zh' in lang.lower() for lang in voice.languages)]
    return engine, chinese_voices

def generate_audio_from_lines(engine, chinese_voices, text_file):
    # 检查文本文件是否存在
    if not os.path.exists(text_file):
        print(f"文件 {text_file} 不存在。")
        sys.exit(1)

    # 逐行读取文本文件
    with open(text_file, 'r', encoding='utf-8') as file:
        lines = file.readlines()

    if not lines:
        print("文件中没有文本内容。")
        sys.exit(1)

    # 检查是否有中文语音
    if not chinese_voices:
        print("未找到中文语音。请确保系统已安装中文TTS语音引擎。")
        sys.exit(1)

    # 用户选择语音(只选择一次,用于所有行)
    print("可用中文语音:")
    for idx, voice in enumerate(chinese_voices):
        print(f"{idx + 1}: {voice.name} (语言: {', '.join(voice.languages)})")

    try:
        voice_index = int(input("请输入选择的语音编号(用于所有行):")) - 1
        if voice_index < 0 or voice_index >= len(chinese_voices):
            raise ValueError
        selected_voice = chinese_voices[voice_index]
    except ValueError:
        print("无效选择,使用默认语音。")
        selected_voice = chinese_voices[0]  # 默认使用第一个中文语音

    # 设置所选语音
    engine.setProperty('voice', selected_voice.id)

    # 为每一行文本生成音频并保存到当前文件夹
    for i, line in enumerate(lines):
        text = line.strip()
        if not text:
            continue  # 跳过空行

        # 打印当前文本,便于调试
        print(f"处理第 {i + 1} 行文本: {text}")

        # 为每行文本生成一个唯一的音频文件名
        output_file = os.path.join(os.getcwd(), f'speech_output_{i + 1}.wav')

        try:
            print(f"正在队列中添加第 {i + 1} 行音频...")
            engine.save_to_file(text, output_file)
        except Exception as e:
            print(f"添加第 {i + 1} 行音频时出错: {e}")
            continue

    # 在循环外调用 runAndWait,处理所有队列
    try:
        print("开始处理所有音频队列...")
        engine.runAndWait()
        print("所有音频生成完成。")
    except Exception as e:
        print(f"处理音频队列时出错: {e}")

    # 打印保存的文件(因为现在一次性生成,无法在循环中打印完成)
    for i, line in enumerate(lines):
        if line.strip():
            output_file = os.path.join(os.getcwd(), f'speech_output_{i + 1}.wav')
            print(f"音频已保存为 {output_file}")

def main():
    # 指定文本文件路径
    text_file = r"D:\test\1.txt"

    # 获取可用的语音
    engine, chinese_voices = populate_voice_list()

    # 为每行文本生成音频
    generate_audio_from_lines(engine, chinese_voices, text_file)

if __name__ == "__main__":
    main()

Python edge-tts

import subprocess
import sys
import os
import asyncio
import random
import tempfile

# 安装 edge-tts 库
def install_edge_tts():
    try:
        subprocess.check_call([sys.executable, "-m", "pip", "install", "edge-tts"])
        print("✅ edge-tts 安装成功!")
    except subprocess.CalledProcessError as e:
        print(f"❌ 安装 edge-tts 失败: {e}")

# 检查是否已安装 edge-tts
try:
    import edge_tts
except ImportError:
    print("edge-tts 未安装,正在安装...")
    install_edge_tts()
else:
    print("edge-tts 已安装。")

from edge_tts import list_voices, Communicate  # Explicit imports for reliability

# Function to list Chinese voices
async def list_chinese_voices():
    voices = await list_voices()
    chinese_voices = [voice for voice in voices if 'zh' in voice['Locale'].lower()]
    chinese_voices.sort(key=lambda v: v['ShortName'])  # Optional: sort for consistency
    return chinese_voices

# Function to convert text to speech with a random voice
async def text_to_speech_with_random_voice(text, chinese_voices, file_path, line_number):
    if not text.strip():
        return None, "Please enter text to convert."

    # Select a random voice
    random_voice = random.choice(chinese_voices)
    voice_short_name = random_voice['ShortName']
    rate_str = "+0%"  # Default rate, can be adjusted as needed
    pitch_str = "+0Hz"  # Default pitch, can be adjusted as needed

    communicate = Communicate(text, voice_short_name, rate=rate_str, pitch=pitch_str)
    
    # Get the directory where the txt file is located
    directory = os.path.dirname(file_path)

    # Save speech to MP3 file with the voice short name appended to the filename
    output_filename = f"line_{line_number}_{voice_short_name}.mp3"
    output_path = os.path.join(directory, output_filename)
    
    await communicate.save(output_path)

    return output_path, None

# Function to process the text file and generate audio for each line
async def process_text_file(file_path, chinese_voices):
    if not os.path.exists(file_path):
        print(f"File '{file_path}' does not exist.")
        return

    with open(file_path, 'r', encoding='utf-8') as file:
        lines = file.readlines()

    for i, line in enumerate(lines, start=1):
        line = line.strip()  # Remove leading/trailing spaces
        if line:
            audio_path, warning = await text_to_speech_with_random_voice(line, chinese_voices, file_path, i)
            if warning:
                print(f"Warning for line {i}: {warning}")
            else:
                print(f"Audio for line {i} saved at: {audio_path}")
        else:
            print(f"Line {i} is empty, skipping...")

# Main function to generate audio from a text file
async def main():
    # Specify the path to the text file
    file_path = r'd:\51.txt'  # Change this to your file path
    
    # List Chinese voices
    chinese_voices = await list_chinese_voices()

    if not chinese_voices:
        print("No Chinese voices available.")
        return

    # Process the text file and generate audio
    await process_text_file(file_path, chinese_voices)

# Run the main function
if __name__ == "__main__":
    asyncio.run(main())

❤️ 转载文章请注明出处,谢谢!❤️