Python实现文字合成音频文件
Posted 冰履踏青云
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python实现文字合成音频文件相关的知识,希望对你有一定的参考价值。
Python技术哪家强?从此我是段子王!
- 1. 创建应用
- 2. 测试语音合成是否可用
- 3. 工具人的觉悟——调个包,造个轮儿?
- 4. 找段子素材合成音频(百度AI版本)
- 5. 整个简单的——pyttsx3版本
- 我将月亮缝入躯体,葬自我于山谷,如果那一天野花疯长,那便是我在讲
最近正好有朋友找我问能不能把他的面试题文字转成音频文件,这还不简单?python除了不能生孩子,啥不能干?
我也就有这个想法试着鼓捣了一下,用网上的段子合成语音文件。
我们这里就用百度AI平台做演示,主要还是因为百度AI平台有很多好玩的高级的功能可以用,
这里带大家熟悉一下百度AI的使用。
我这里一共做了两个版本的一个百度AI版本的,一个pyttsx3版本的都能达到目的。
1. 创建应用
百度AI开放平台的网址:百度AI,只要注册过百度帐号就可以登录使用。
鼠标放到开放能力,
点击语音合成:
点击立即使用,
可以看到这个控制台提供各种优质的付费服务,当然,我们这里就不花钱了,直接点击领取免费资源,点击语音合成
点击0元领取:
需要的都可以领,有效期大概都是半年左右,没事了自己玩玩也挺有趣的。
可能是访问者过多网站不太稳定?我这老是这样:
领完了看资源列表是这样:
它提示领取的免费测试资源预计30分钟内生效,刷了几分钟都没出现,就停下来该干啥干啥,30分钟后再来看。
听听音乐,10分钟后,我来刷一下:
发现已经可以用了。
接下来开始创建应用:
随便取个名字,我这里填了个test
拉到最下面,把必填的信息填一下
点击立即创建就🆗了。
感兴趣的可以看一下人家的应用文档,我们这里就直接开整了,看一下应用列表:
看到APIKey,SecretKey了,这两个是调用服务的必填参数。
2. 测试语音合成是否可用
上面我们已经拿到APIKey,SecretKey了,
接下来我们直接上代码,整一段话测试一下合成语音的效果:
# -*- coding: utf-8 -*-
import time
import requests
import urllib.parse
import urllib.request
def fetch_token(): # 提交请求,拿到token
api_key = "TbCtGOSc5xxxxxxxxxx" # 使用百度AI平台管理中心中创建的应用的API Key
secret_key = "wsiE0t8Q7xxxxxxx" # 使用百度AI平台管理中心中创建的应用的Secret Key
token_url = "https://openapi.baidu.com/oauth/2.0/token"
# print("fetch token begin")
params = "grant_type": "client_credentials",
"client_id": api_key,
"client_secret": secret_key
r = requests.get(url=token_url, params=params)
if r.status_code == 200:
rstr = r.json()
# print(r.text)
# print(rstr['access_token'])
tok = rstr['access_token']
return(tok)
else:
print(r.text)
print('请求错误!')
if __name__ == '__main__':
token = fetch_token()
TTS_URL = "https://tsn.baidu.com/text2audio"
text = """
小时候吃了800包德芙,我妈把我从16楼扔下去,笑死,我一路顺滑到底,根本死不了。
小时候吃了两箱士力架,我妈把我锁地下室两年,笑死,根本不饿。
小时候偷喝了我爸的红牛,被我爸追着打了三天三夜还在跑,笑死,我的能量超乎你想象。
小时候偷喝了10瓶雪碧,我妈罚我站在太阳底下,笑死,爽快的一批。
小时候偷玩真传奇,我妈罚我一年没有零花钱,笑死,根本不缺钱。
小时候一次吃了10盒炫迈,我妈罚我跑几百公里,笑死,根本停不下来。
小时候偷吃100支夏日奇兵,我妈罚我站在太阳底下暴晒2个月,笑死,太阳都给冻住。
小时候搞对象被知道了,我妈让我和对象分手,笑死,根本就分不完。。。
""".encode('utf8')
# 发音人选择, 基础音库:0为度小美,1为度小宇,3为度逍遥,4为度丫丫,
# 精品音库:5为度小娇,103为度米朵,106为度博文,110为度小童,111为度小萌,默认为度小美
PER = 103
# 语速,取值0-15,默认为5中语速
SPD = 5
# 音调,取值0-15,默认为5中语调
PIT = 5
# 音量,取值0-9,默认为5中音量
VOL = 5
# 下载的文件格式, 3:mp3(default) 4: pcm-16k 5: pcm-8k 6. wav
AUE = 3
FORMATS = 3: "mp3", 4: "pcm", 5: "pcm", 6: "wav"
FORMAT = FORMATS[AUE]
data = urllib.parse.urlencode('tex': text, 'per': PER, 'tok': token, 'cuid': '20009514', 'ctp': 1, 'lan': 'zh', 'aue': AUE)
# print('test on Web Browser' + TTS_URL + '?' + data)
req = requests.post(TTS_URL, data)
print(req.status_code)
if req.status_code == 200:
# print(req.content)
result_str = req.content
save_file = time.strftime("%Y%m%d%H%M%S", time.localtime()) + '.' + FORMAT
with open(save_file, 'wb') as of:
of.write(result_str)
print('success!')
else:
print('has error!')
执行一下,看一下效果:
成功生成mp3文件,听一下效果还可以。
以上代码小伙伴如果要测试,只需要把自己的APIKey,SecretKey这两个参数替换上就可以用了,想换声音的话就看注释改PER参数。
3. 工具人的觉悟——调个包,造个轮儿?
上面我们已经实现了语音合成的测试,但代码毕竟还是通用性有点低,你想想,以后总不能有这需求咱们都这样写一遍吧,即使是复制粘贴也不雅观,代码过度冗余就显得太low了。
想要做个好的工具人,那就尽量让自己整的东西用起来不费力,这样才能更好的摸鱼!
那接下来咱们就自己动手,把上面的代码改造的具有通用性一点,想想咱们的需求也就是把文本转成语音而已,那我们需要的大概就是把文本内容传进去,然后它给我门生成mp3音频,最好带个标题给音频取个名字,想到咱就干,开整:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2022/3/11 18:15
# @Author : 冰履踏青云
# @File : speekSound.py
import requests
import urllib.parse
import urllib.request
def fetch_token(): # 提交请求,拿到token
api_key = "TbCtGOSc5exxxxxx" # 使用百度AI平台管理中心中创建的应用的API Key
secret_key = "wsiE0t8Q7xxxxxxxxxx" # 使用百度AI平台管理中心中创建的应用的Secret Key
token_url = "https://openapi.baidu.com/oauth/2.0/token"
# print("fetch token begin")
params = "grant_type": "client_credentials",
"client_id": api_key,
"client_secret": secret_key
r = requests.get(url=token_url, params=params)
if r.status_code == 200:
rstr = r.json()
# print(r.text)
# print(rstr['access_token'])
tok = rstr['access_token']
return(tok)
else:
print(r.text)
print('网络请求出错,无法获取token!')
def gen_speech(content,title):
token = fetch_token()
TTS_URL = "https://tsn.baidu.com/text2audio"
text = content.encode('utf8')
# 发音人选择, 基础音库:0为度小美,1为度小宇,3为度逍遥,4为度丫丫,
# 精品音库:5为度小娇,103为度米朵,106为度博文,110为度小童,111为度小萌,默认为度小美
PER = 103
# 语速,取值0-15,默认为5中语速
SPD = 5
# 音调,取值0-15,默认为5中语调
PIT = 5
# 音量,取值0-9,默认为5中音量
VOL = 5
# 下载的文件格式, 3:mp3(default) 4: pcm-16k 5: pcm-8k 6. wav
AUE = 3
FORMATS = 3: "mp3", 4: "pcm", 5: "pcm", 6: "wav"
FORMAT = FORMATS[AUE]
data = urllib.parse.urlencode(
'tex': text, 'per': PER, 'tok': token, 'cuid': '20009514', 'ctp': 1, 'lan': 'zh', 'aue': AUE)
# print('test on Web Browser' + TTS_URL + '?' + data)
req = requests.post(TTS_URL, data)
# print(req.status_code)
if req.status_code == 200:
# print(req.content)
result_str = req.content
save_file = title + '.' + FORMAT
with open('./音频文件//' + save_file, 'wb') as of:
of.write(result_str)
# print('%s合成成功!'%title)
else:
print('合成语音时,网络请求出错!!!')
这样就简单的封装好合成语音模块了,下次再用就直接调speekSound.py里面的gen_speech方法就可以了。
整合好目录,把合成后的音频文件统一放入音频文件夹里,目录结构:
4. 找段子素材合成音频(百度AI版本)
接下来我们写个请求程序获取段子网素材在线合成音频。
找个段子网站,咱直接开干:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2022/3/11 18:30
# @Author : 冰履踏青云
# @File : duanzi.py
from gen_sound.speekSound import gen_speech
import requests
from lxml import etree
from requests.packages.urllib3.exceptions import InsecureRequestWarning
#关闭安全请求警告
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
url = 'https://ishuo.cn/duanzi'
headers =
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/98.0.4758.102 Safari/537.36"
res = requests.get(url,headers=headers,verify=False).text
# print(res)
html = etree.HTML(res)
li_list = html.xpath("//div[@id='content']/div[@id='list']/ul/li")[:20] # 取前20个
for li in li_list:
content = li.xpath('./div[1]/text()')[0]
title = li.xpath('./div[2]/a/text()')[0]
# print(content,title)
gen_speech(content,title)
print(title,'合成音频成功...')
这里我做测试,只取了前20条段子,执行结果:
看一下音频文件夹:
至此我们的目的就达到了。
5. 整个简单的——pyttsx3版本
有人就说了,我就不想用百度AI,想更省事儿,那也很简单,
python本身就有一个pyttsx3模块可以实现这个功能,使用之前需要安装一下这个模块:
pip install pyttsx3
工具整好,准备开干:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2022/3/11 19:51
# @Author : 冰履踏青云
# @File : pyttsx3合成语音.py
import pyttsx3
engine = pyttsx3.init() # 模块初始化
str='唉,这个世界对修仙者太不走好了,我去医院看病,医生非得打了我的金丹,说那是结石,刚出门诊就看到一个女孩子,年纪轻轻,就拥有着恐怖的修为,可被一帮人扭送着摘掉了她的元婴,旁边的旅馆,还有两位合体期的大神被抓进了大牢,向前走,有位出窍期的巨擘被烧掉了肉身,唉'
outFile = 'xiu.mp3' # 输出格式
rate = engine.getProperty('rate') # 获取语速
engine.setProperty('rate',rate-10) # 调整语速
engine.save_to_file(str,outFile) # 这个位置必须放在播报Unicode字符串前面,
# engine.say(str) # 设置要播报的Unicode字符串
engine.runAndWait() # 等待语音播报完毕
执行一下,感觉效果还可以。然后需要把朋友面试题的pdf或者其他形式的文档用python读取,替换掉str就完事了。
本来是不想写的,想想那么简单怎么还有人不会?
但是我怕万一呀,这里我也顺带写一份pyttsx3版本的吧,没啥难度,直接上代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2022/3/11 20:06
# @Author : 冰履踏青云
# @File : daunzi2.py
import requests
from lxml import etree
from requests.packages.urllib3.exceptions import InsecureRequestWarning
import pyttsx3
#关闭安全请求警告
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
def compound_sound(content,title):
'''
合成音频模块
:param content:
:param title:
:return:
'''
try:
engine = pyttsx3.init() # 模块初始化
str = content
outFile = './音频文件夹//.mp3'.format(title) # 输出格式
rate = engine.getProperty('rate') # 获取语速
engine.setProperty('rate', rate - 10) # 调整语速
engine.save_to_file(str, outFile) # 这个位置必须放在播报Unicode字符串前面,
# engine.say(str) # 设置要播报的Unicode字符串
engine.runAndWait() # 等待语音播报完毕
except Exception as e:
print('合成出错!!!')
print(e)
def start_make():
'''发送请求获取段子,并合成音频'''
url = 'https://ishuo.cn/duanzi'
headers =
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36"
res = requests.get(url,headers=headers,verify=False).text
# print(res)
html = etree.HTML(res)
li_list = html.xpath("//div[@id='content']/div[@id='list']/ul/li")[:10]
for li in li_list:
content = li.xpath('./div[1]/text()')[0]
title = li.xpath('./div[2]/a/text()')[0]
# print(content,title)
compound_sound(content,title)
print(title,'合成音频成功...')
if __name__ == '__main__':
start_make()
效果和百度AI一样(就是声音没有百度AI的度米朵好听):
我将月亮缝入躯体,葬自我于山谷,如果那一天野花疯长,那便是我在讲
文章到此结束,欢迎一键三连,点个赞,收个藏啥的,我有故事你有酒,好好交流不分手!哈哈哈!下次见!
以上是关于Python实现文字合成音频文件的主要内容,如果未能解决你的问题,请参考以下文章