在线文本转语音工具的实现

news2024/12/23 18:31:11

文章目录

  • 文章最下面有工具链接!
  • 前言
  • edge-tts库
    • 1.首先使用pip安装这个库
    • 2.写一段示例代码
    • 3.多线程
  • pydub库
    • 1.介绍
    • 2.示例
  • 将他们整合起来
  • 我把他们部署到了我的服务器上,可以在线使用
  • 点我使用工具

文章最下面有工具链接!

前言

最近有文字转语音功能的需求,虽然也有一些免费工具,不过并没有找到好用的在线的文本转语音工具,因此便有了这篇文章。

edge-tts库

这是一个基于微软edge浏览器大声朗读功能的python库,作者将其进行封装,因此我们可以借由它来实现文字转语音功能,那么首先我先介绍一下这个库。edge-tts的github地址

1.首先使用pip安装这个库

pip3 install edge_tts 

2.写一段示例代码

import asyncio
import edge_tts

Content = "注意看,这是一段文字转语音的测试"
voiceName = "zh-TW-YunJheNeural"
output = "sound.mp3"
rate = '+5%'
volume = '+0%'
pitch = '+0Hz'

async def main():
    communicate = edge_tts.Communicate(text = Content, voice=voiceName ,rate=rate, volume=volume,pitch=pitch)
    await communicate.save(output)
  
asyncio.run(main()) 

asyncio.run 是 Python 标准库中 asyncio 模块提供的一个函数,用于运行一个异步函数直到它完成。它通常用于简化异步代码的执行,特别是在运行一个完整的异步应用程序时,而edge_tts所需要的就是这么一个异步执行,使用edge_tts.Communicate来生成音频内容,然后使用communicate.save来将文件保存到本地路径,其中text为所需要的文本,voice为所需要的音色,这个一会介绍,rate为语速,volume为音量,默认0就是满的,pitch为音调,后三个所接收的数据需要带上 正负号 数字 百分比的形式,其中pitch需要 正负号 数字 Hz的形式。

voice为音色参数,对于音色的获取,需要在安装完库之后在cmd里输入

edge-tts --list-voices

来查询,我列举一下这个库所支持的中文音色:

            { "Value": "zh-CN-XiaoxiaoNeural", "text": "晓晓" },
            { "Value": "zh-CN-XiaoyiNeural", "text": "小艺" },
            { "Value": "zh-CN-YunjianNeural", "text": "云建" },
            { "Value": "zh-CN-YunxiNeural", "text": "云溪" },
            { "Value": "zh-CN-YunxiaNeural", "text": "云霞" },
            { "Value": "zh-CN-YunyangNeural", "text": "云阳" },
            { "Value": "zh-CN-liaoning-XiaobeiNeural", "text": "东北小贝" },
            { "Value": "zh-CN-shaanxi-XiaoniNeural", "text": "山西小妮" },
            { "Value": "zh-HK-HiuGaaiNeural", "text": "粤语小妹" },
            { "Value": "zh-HK-HiuMaanNeural", "text": "粤语小妹2" },
            { "Value": "zh-HK-WanLungNeural", "text": "粤语小哥" },
            { "Value": "zh-TW-HsiaoChenNeural", "text": "台湾小妹" },
            { "Value": "zh-TW-HsiaoYuNeural", "text": "台湾小妹2" },
            { "Value": "zh-TW-YunJheNeural", "text": "台湾小哥" }

3.多线程

如果你跟着教程做了下来,你可以尝试使用一段超过5000字的长文本,你会发现生成速度明显慢了下来,我们可以使用多线程来同时生成多段文本,然后再把他们拼接到一起,这样速度便会有明显的提升
下面是一段多线程同步生成文件的测试,我们需要在项目目录下创建texts的文件夹,里面放上我们想要生成的文本:

import asyncio
import time
import edge_tts
import os

async def convert(text, file_name) -> None:
    start_time = time.time()
    communicate = edge_tts.Communicate(text, "zh-CN-XiaoxiaoNeural")
    await communicate.save(f"sounds/{file_name}.mp3")
    print(f"{file_name}用时:{int(time.time() - start_time)}秒")
async def main():
    # 创建输出文件夹
    if not os.path.exists("sounds"):
        os.makedirs("sounds")
    tasks = []
    # 遍历输入文件夹
    for root, dirs, files in os.walk("texts"):
        for file in files:
            # 将文件中的文本读出来
            with open(os.path.join(root, file), "r", encoding='utf-8') as text_file:
                text = text_file.read()
                # 获取文件名
                file_name, ext = os.path.splitext(file)
                # 加入任务列表
                tasks.append(convert(text, file_name))
    # 等待所有任务完成
    await asyncio.gather(*tasks)


asyncio.run(main())

可以看到这几篇文章都在同步下载,那么如果我们有一段很长的长文本,那么就可以按照这种方式来快速生成了。

pydub库

1.介绍

pydub 是一个用于处理音频文件的 Python 库,对音频进行各种操作变得更加容易。以下是一些 pydub 的主要功能:

音频格式转换: pydub 支持多种音频格式之间的转换,例如将 MP3 转换为 WAV 或反之。

音频剪辑和拼接: 你可以使用 pydub 对音频进行剪辑或拼接,合并多个音频文件。

音频格式调整: 调整音频的采样率、声道数、比特率等属性。

音频切片: 从音频文件中提取特定时间范围的片段。

音频效果: 提供一些简单的音频效果,例如增加音量、降低音量、应用均衡器等

我们只需要用到其中的音频拼接功能就可以,需要注意的是,使用这个库需要用到ffmpeg,对于ffmpeg的安装方法请移步至此:ffmpeg官网

2.示例

使用它来拼接音频是十分简单的,这是一段示例代码:

from pydub import AudioSegment
#读取音频文件
audio1 = AudioSegment.from_file("file1.wav")
audio2 = AudioSegment.from_file("file2.wav")
#拼接音频文件
merged_audio0=audio1+audio2
#保存拼接后的音频文件
merged_audio.export("merged.wav", format="wav")

将他们整合起来

需要texts,cache,download三个文件夹,其中texts里为你的文章,然后pwd需要设置为项目运行路径

import asyncio
import edge_tts
import time
from pydub import AudioSegment
import hashlib

pwd = "/var/www/html/sound"

rate = '+0%'
volume = '+0%'
pitch = '+0Hz'
def calculate_8_digit_md5(input_string):
    md5 = hashlib.md5()
    md5.update(input_string.encode('utf-8'))
    md5_hash = md5.hexdigest()[:8]
    return md5_hash
def get_current_time():
    current_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
    return current_time


async def convert(text, file_name, count,voice_name) -> None:
    global result
    start_time = time.time()
    communicate = edge_tts.Communicate(text=text,voice=voice_name,rate=rate,volume=volume,pitch=pitch)
    await communicate.save(pwd+f"/cache/{file_name}{count}.mp3")
    print(f"{file_name}用时:{int(time.time() - start_time)}秒")
    
def split_and_terminate(input_string, chunk_size=3000):
    res = []
    start = 0
    while start < len(input_string):
        # 截取指定大小的片段
        chunk = input_string[start:start + chunk_size]
        if start + chunk_size < len(input_string):
            last_comma = chunk.rfind(',')
            last_period = chunk.rfind('。')
            last_punctuation = max(last_comma, last_period)
            if last_punctuation != -1:
                chunk = chunk[:last_punctuation + 1]
        res.append(chunk)
        start += len(chunk)
    return res

async def main():
    print("md5:"+md5)
    result = split_and_terminate(text)
    tasks = []
    for index, chunk in enumerate(result):
        tasks.append(convert(chunk, md5,str(index+1),"zh-CN-XiaoxiaoNeural"))
    await asyncio.gather(*tasks)

def save_string_to_file(data, file_path):
    try:
        with open(file_path, 'w', encoding='utf-8') as file:
            file.write(data)
        print(f"字符串已成功保存到文件: {file_path}")
    except Exception as e:
        print(f"保存文件时发生错误: {e}")

if __name__ == "__main__":
    global text,md5
    with open(pwd+"/texts/测试.txt", "r", encoding='utf-8') as text_file:
        text = text_file.read()
        md5 = calculate_8_digit_md5(text + str(time.time()))
    asyncio.run(main())
    print('音频下载完成')
    result = AudioSegment.from_file(pwd+"/cache/" + md5 + "1.mp3")
    print('第1段合成完成')
    count = len(split_and_terminate(text))
    for i in range(2,count+1):
        result += AudioSegment.from_file(pwd+"/cache/" + md5 + str(i) + ".mp3")
        print('第' + str(i) + '段合成完成')
    result.export(pwd+"/download/"+md5+".mp3", format="mp3")
    print(md5+".mp3生成成功")




我把他们部署到了我的服务器上,可以在线使用

点我使用工具

在这里插入图片描述
这个网站还有进度条功能和日志显示功能,他们都是用原生html实现的,如果有人感兴趣,评论区说下,我再出期文章!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1370167.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

将Llama2上下文长度扩展100倍;效率更高的SeTformer;LLM准确度基本不变加速1.56×;FreeTalker

本文首发于公众号&#xff1a;机器感知 将Llama2上下文长度扩展100倍&#xff1b;效率更高的SeTformer&#xff1b;LLM准确度基本不变加速1.56&#xff1b;FreeTalker Latte: Latent Diffusion Transformer for Video Generation 本文使用Latent Diffusion Transformer(Latte…

程序媛的mac修炼手册-- 终端(terminal)常用命令

「终端&#xff08;terminal&#xff09;」相当于macOS的一个 App &#xff0c;它的特殊之处是&#xff0c;它是管理其它App的App&#xff0c;操作主要通过命令行界面 (CLI) 。 相比于我们日常熟悉的用户界面&#xff08;User Interface&#xff0c;UI&#xff09;&#xff0c…

go image.DecodeConfig 和image.Decode 不能同时使用吗

问题场景&#xff1a;在同时使用go image.DecodeConfig 和image.Decode获取图片信息时&#xff0c;报错提示&#xff1a; 无法读取图像配置 image: unknown format package mainimport ("fmt""github.com/golang/freetype""image""image/d…

GPT在地学、GIS、气象、农业、生态、环境等领域应用教程

详情点击链接&#xff1a;GPT在地学、GIS、气象、农业、生态、环境等领域应用教程 一开启大模型 1 开启大模型 1)大模型的发展历程与最新功能 2)大模型的算法构架与底层逻辑 3)大模型的强大功能与应用场景 4)国内外经典大模型&#xff08;ChatGPT、LLaMA、Gemini、DALLE、…

【echarts】雷达图参数详细介绍

1. 详细示例 var option {tooltip: {trigger: item},radar: {startAngle: 90,//第一个指示器轴的角度&#xff0c;默认90indicator: [// 指示器{ name: Category A, max: 220 },// name:指示器名称{ name: Category B, max: 200 },// max:指示器的最大值&#xff0c;可选&…

【JAVA】throw 和 throws 的区别?

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a; JAVA ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 throw&#xff1a; throws&#xff1a; 区别&#xff1a; 作用&#xff1a; 使用位置&#xff1a; 个数&#xff1a; 应…

第1章 初识JavaScript

学习目标 了解JavaScript基本概念&#xff0c;能够说出JavaScript的作用、由来、组成和特点 熟悉常见浏览器的特点&#xff0c;能够说出浏览器的组成以及作用 掌握下载和安装Visual Studio Code编辑器&#xff0c;能够独立完成编辑器的下载和安装 掌握JavaScript代码引入方式…

【forwardRef与useImperativeHandle】

1、 2、 3、 4、代码 1、index.tsx代码 import React, {useRef, useEffect} from react import MyInput from "./InputItem";export default function Index() {const ref useRef<any>(null);useEffect(() > {ref.current?.focus();}, [])return (<&…

安达发|APS计划与排程软件之超级BOM功能

在制造业中&#xff0c;物料清单&#xff08;BOM&#xff09;是一个重要的概念&#xff0c;它描述了产品的组成结构和各个部件之间的关系。随着制造业的发展&#xff0c;对于生产计划和排程的要求也越来越高&#xff0c;因此APS&#xff08;高级计划与排程&#xff09;软件应运…

2023年,To B资本航船走向哪了?

国内To B领域在去掉泡沫、结束资本狂欢之后&#xff0c;投资决策愈加理性。但与此同时&#xff0c;下滑的步伐正在放慢&#xff0c;交易数量和金额的降低逐渐放缓&#xff0c;市场逐渐走向稳定。 作者|斗斗 编辑|皮爷 出品|产业家 2023年&#xff0c;在一众业内人士的眼中&…

openai API key 提示你的卡被拒绝怎么办?

openai API key 对于IP的要求非常的严格&#xff0c;以前你开腾讯云、阿里云的服务器都可以绑定、现在就不行了&#xff0c;一定要纯净的IP才可以绑定 一、排除法 1、首先确保自己的账号是没有被封的&#xff0c;可以正常使用的 2、确保银行卡是可以支持openai的银行卡 3、…

IDEA的lombok失效导致工程代码编译build失败的问题处理

今天也是奇了怪了&#xff0c;打包工程&#xff0c;编译始终失败&#xff0c;明明代码符号存在的 解决办法就是&#xff1a;-Djps.track.ap.dependenciesfalse

嵌入式(八)电源低功耗管理 | 五种运行模式 模式转换 睡眠定时器唤醒

文章目录 1 低功耗基本介绍1.1 五种运行模式 2 低功耗控制相关寄存器3 睡眠唤醒实现方式3.1 系统睡眠定时器唤醒 1 低功耗基本介绍 对于嵌入式系统而言&#xff0c;一个非常重要的内容就是低功耗&#xff0c;尽可能减少电量损耗&#xff0c;然后获得更多的续航时间 当然功耗越…

UG装配-布置

UG装配中&#xff0c;当一个产品在不同情况下具有不同的形态的时候&#xff0c;为了快速进行展示&#xff0c;我们可以使用布置命令. 我们可以直接在工具栏布置中&#xff0c;或者在装配导航器中右键单击装配体&#xff0c;选择布置-编辑&#xff0c;添加不同不同的布置页面 使…

模拟算法(模拟算法 == 依葫芦画瓢)万字

模拟算法 基本思想引入算法题替换所有的问号提莫攻击Z字形变换外观数列数青蛙 基本思想 模拟算法 依葫芦画瓢解题思维要么通俗易懂&#xff0c;要么就是找规律&#xff0c;主要难度在于将思路转换为代码。 特点&#xff1a;相对于其他算法思维&#xff0c;思路比较简单&#x…

Docker简介、基本概念和安装

Docker简介、基本概念和安装 1.docker简介 1.1 什么是docker Docker 最初是 dotCloud 公司创始人 Solomon Hykes (opens new window)在法国期间发起的一个公司内部项目&#xff0c;它是基于 dotCloud 公司多年云服务技术的一次革新&#xff0c;并于 2013 年 3 月以 Apache 2…

Power BI - 5分钟学习修改数据类型

每天5分钟&#xff0c;今天介绍Power BI修改数据类型 Power BI加载数据时&#xff0c;会尝试将源列的数据类型转换为更高效的存储、计算和数据可视化的数据类型。 例如&#xff0c;如果从Excel导入的值的列没有小数值&#xff0c;Power BI Desktop会将整个数据列转换为整数数据…

HCIA-Datacom题库(自己整理分类的)_17_简单的命令判断【11道题】

1.华为AR路由器的命令行界面下&#xff0c;save命令的作用是保存当前的系统时间。 解析&#xff1a;Save保存配置 2.VRP界面下&#xff0c;使用命令delete vrpcfg.zp删除文件&#xff0c;必须在回收站中清空&#xff0c;才能彻底删除文件。√ 解析&#xff1a;delete删除到回…

“高端”的位运算

王有志&#xff0c;一个分享硬核Java技术的互金摸鱼侠加入Java人的提桶跑路群&#xff1a;共同富裕的Java人 原计划迭代作为预备知识的收尾&#xff0c;不过在解2的幂和4的幂时&#xff0c;想到关于数字2的问题可以通过位运算去解决&#xff0c;因此补充了关于位运算的内容。 …

Spring循环引用和三级缓存

前言 Spring 解决 Bean 之间的循环引用关系用到了三级缓存&#xff0c;那么问题来了。三级缓存是怎么用的&#xff1f;每一层的作用是什么&#xff1f;非得用三级吗&#xff1f;两级缓存行不行&#xff1f; 理解循环引用 所谓的“循环引用”是指 Bean 之间的依赖关系形成了一…