#!/usr/bin/env python3 """ TTS 转换脚本 - 支持多语言 支持:中文(zh)、英文(en)、日文(jp) """ import argparse import asyncio import edge_tts import sys from pathlib import Path # 语音配置 VOICES = { 'zh': 'zh-CN-XiaoxiaoNeural', # 中文-晓晓 'zh-hk': 'zh-HK-HiuMaanNeural', # 粤语 'en': 'en-US-AriaNeural', # 英语-美音 'en-gb': 'en-GB-SoniaNeural', # 英语-英音 'jp': 'ja-JP-NanamiNeural', # 日语 'kr': 'ko-KR-SunHiNeural', # 韩语 } # 默认语速 DEFAULT_RATE = "+0%" async def convert_text_to_speech(text: str, voice: str, output_file: str, rate: str = DEFAULT_RATE): """将文本转换为语音""" communicate = edge_tts.Communicate(text, voice, rate=rate) await communicate.save(output_file) print(f"✅ 已保存: {output_file}") async def convert_file(input_file: str, lang: str = 'auto', output_file: str = None, rate: str = DEFAULT_RATE): """转换文件""" input_path = Path(input_file) if not input_path.exists(): print(f"❌ 文件不存在: {input_file}") sys.exit(1) # 读取文本 with open(input_file, 'r', encoding='utf-8') as f: text = f.read() # 自动检测语言(简单判断) if lang == 'auto': lang = detect_language(text) print(f"🔍 检测到语言: {lang}") # 获取语音 voice = VOICES.get(lang, VOICES['zh']) # 确定输出文件名 if output_file is None: output_file = str(input_path.with_suffix('.mp3')) # 转换 print(f"🎙️ 使用语音: {voice}") print(f"📝 转换: {input_file} -> {output_file}") await convert_text_to_speech(text, voice, output_file, rate) return output_file def detect_language(text: str) -> str: """简单语言检测""" # 日文假名 if any('\u3040' <= c <= '\u309f' or '\u30a0' <= c <= '\u30ff' for c in text[:100]): return 'jp' # 韩文 if any('\uac00' <= c <= '\ud7af' for c in text[:100]): return 'kr' # 中文 if any('\u4e00' <= c <= '\u9fff' for c in text[:100]): return 'zh' # 默认英文 return 'en' def main(): parser = argparse.ArgumentParser(description='文本转语音工具') parser.add_argument('input', help='输入文本文件') parser.add_argument('--lang', '-l', default='auto', choices=['auto', 'zh', 'zh-hk', 'en', 'en-gb', 'jp', 'kr'], help='语言代码 (默认: auto)') parser.add_argument('--output', '-o', help='输出音频文件') parser.add_argument('--rate', '-r', default=DEFAULT_RATE, help='语速调整,如 "+10%" 或 "-10%"') parser.add_argument('--list-voices', action='store_true', help='列出所有可用语音') args = parser.parse_args() if args.list_voices: print("可用语音:") for code, voice in VOICES.items(): print(f" {code}: {voice}") return # 运行转换 asyncio.run(convert_file(args.input, args.lang, args.output, args.rate)) if __name__ == '__main__': main()