百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

三个Python文字语音转换的案例

myzbx 2025-02-15 00:15 13 浏览

一、Python文字转语音项目

近日做了个文本转语音的小项目,主功能接百度智能云的API很顺利,但3个小细节处理很费了些事。就像生活中往往一些不起眼的小角色更狠、更能给人添堵,做项目也是一样。特分享记录一下,先看看项目界面和运行效果:

主功能:在顶部输入框中输入英语单词或语句,点击右侧的三个按钮,识别输入的文本,转换为语音,并进行播放。读单词模式时,中间灰色区域,同步显示英语单词和中文翻译。

1、主功能文本转语音试了三种方法,感觉百度智能云的语音技术甩别的几条街,不知是不是百度曾经的all in ai留下的战果,翻译也就顺带用他家的了。

2、通过“文件导入”功能导入文本时,打开文本、读取文本都不难,但遇到无法解码的特殊字符,只一个就导致读取失败,字符解码的细节容易被忽略,却常常出来惹事。

3、“读单词”模式,通过分割符将文本分割成一个个单词,再逐个进行语音转换,播放。但由于playsound播放文件后,资源不会被放弃,导致无法逐个播放,这是本项目最硬的茬,通过修改源库代码方解决。

4、“读单词”模式,播放语音时,中间同步显示英语和翻译,实际却是等全部读完了,才显示最后一个单词及翻译,后通过添加线程解决。

详细过程:

一、主功能,接百度语音技术解决文本转语音。

首先,需要注册百度智能云,添加语音技术应用,获得ID、key,如下图:

接下来写码就ok了。

def text_to_voice(str, cs):

APP_ID = '************************'

API_KEY = '************************'

SECRET_KEY = '************************'

client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)

result = client.synthesis(str, 'zh', 1, cs)

if not isinstance(result, dict):

with open('auido.mp3', 'wb') as f:

f.write(result)

if __name__ == "__main__":

cs = {'vol': 5, 'per': 1, 'spd': 8}

text_to_voice('goodmorning', cs)

代码很简单,头三行***为从前面获得的ID、key。‘str’为要读取的文本内容,‘cs’为播放声音的参数,'vol'音调,'per'1为男声,0为女声,'spd'为语速。作为参数带入函数块,利于界面交互。

二、文件导入写入文本

def open_file():

global word

path = './'

filename = filedialog.askopenfilename(

title=u'选择文件',

filetypes=[("记事本", ".txt")],

initialdir=(os.path.expanduser(path)))

if filename != '':

f = open(filename, 'rb')

lines = f.readlines()

n = 1

for line in lines:

line = line.strip().decode('utf-8')

if line != '':

word = word + line

n += 1

e.delete(0, 'end')

e.insert(0, word)

e.delete(0, 'end')为删除文本框原内容

e.insert(0, word)将word里的内容显示在文本框里。

读取生成word内容时,line = line.strip().decode('utf-8')用decode解码,可以应付多数情况了。

三、解决不能循环播放mp3文件的问题

导入模块from playsound import playsound

直接播放playsound('auido.mp3')

但在for循环里批量播放时报错,因为playsound库源码里没有关闭文件的代码,从网上借鉴到的做法,修改源码,增加关闭功能。

打开python安装路径,找到playsound.py文件打开,

在下面的位置,增加红框内的代码

增加的代码为:

while True:

if winCommand('status', alias, 'mode').decode() == 'stopped':

winCommand('close', alias)

break

保存后,再循环运行playsound('auido.mp3')就没问题了。

将一组单词逐个进行阅读的代码:

def read_text(text):

cs['vol'] = s1.get()

cs['spd'] = s2.get()

cs['per'] = v.get()

ttv.text_to_voice(text, cs)

playsound('auido.mp3')

def one_by_one():

tt = re.split(',|\.|\?|。|,', content.get())

if tt != '':

for t in tt:

if t != '':

label22['text'] = t.strip() + '\n' + '\n' + en_to_zh.fy(t)

read_text(t)

time.sleep(1)

四、多线程同步显示单词及翻译

上面label22['text'] = t.strip() + '\n' + '\n' + en_to_zh.fy(t)中en_to_zh.fy(t)即为翻译的中文,首先导入自己写的含翻译功能py文件en_to_zh,再利用文件里的fy函数块进行翻译得到中文。en_to_zh.py代码为百度翻译api提供的代码,只修改为自己的id和key,然后设置return语句返回获得的中文即可:

import http.client

import hashlib

import urllib

import random

import json

def fy(txt):

appid = '*************************' # 填写你的appid

secretKey = '*************************' # 填写你的密钥

httpClient = None

myurl = '/api/trans/vip/translate'

fromLang = 'en' #原文语种

toLang = 'zh' #译文语种

salt = random.randint(32768, 65536)

q = txt#'apple'

sign = appid + q + str(salt) + secretKey

sign = hashlib.md5(sign.encode()).hexdigest()

myurl = myurl + '?appid=' + appid + '&q=' + urllib.parse.quote(

q) + '&from=' + fromLang + '&to=' + toLang + '&salt=' + str(

salt) + '&sign=' + sign

try:

httpClient = http.client.HTTPConnection('api.fanyi.baidu.com')

httpClient.request('GET', myurl)

# response是HTTPResponse对象

response = httpClient.getresponse()

result_all = response.read().decode("utf-8")

result = json.loads(result_all)

return result['trans_result'][0]['dst']

except Exception as e:

print(e)

finally:

if httpClient:

httpClient.close()

在原代码里仅加了“return result['trans_result'][0]['dst']”语句就好。该处的id和key是百度翻译里获取的,与前面的语音技术id是两码事,但注册操作方法一样。

上面获得了内容,但我们需要在for循环里动态显示在label框里,却无法实现,只能在for循环完成后,再显示最后一次的结果,显然这不是我们要的。这是因为单线程不能同时干两件事导致的,解决方法是增加线程,让同时处理两件事。

在按钮“读单词”的触发程序块里设置增加线程的代码:

def read_one():

read_text('请跟我读:')

t = threading.Thread(target=one_by_one, args=(), name='thread-refresh')

t.setDaemon(True)

t.start()

真正的运行阅读代码写在函数one_by_one()里。

五、交互界面代码

为丰富播放体验,设置了单选按钮、数据拉条进行CS参数设置,具体过程不细讲,代码附上:

if __name__ == "__main__":

cs = {'vol': 8, 'per': 0, 'spd': 4}

root = tkinter.Tk()

root.title("英语领读")

root.geometry('660x420-20+30')

# 第0行

ft0 = tkFont.Font(family='楷体', size=15)

titlelabel = tkinter.Label(root, text='输入或通过文件导入阅读内容', width=40, font=ft0, anchor='s')

titlelabel.grid(row=0, column=0, columnspan=6, pady=10, sticky='S')

# 第1行

pic_11 = tkinter.PhotoImage(file='pic/99.png')

bt11 = tkinter.Button(root, text='从文件导入', image=pic_11, width=65, height=25, command=open_file)

bt11.grid(row=1, column=0, pady=8, padx=5, columnspan=1, sticky='NW')

content = tkinter.StringVar()

e = tkinter.Entry(root, textvariable=content, font=ft0, width=46)

e.grid(row=1, column=1, columnspan=4, pady=8, sticky='NW')

content.set('hai, nice to meet you!')

pic_1 = tkinter.PhotoImage(file='pic/12.png')

bt12 = tkinter.Button(root, text='清空', width=8,

command=clear) #, image=pic_1

bt12.grid(row=1, column=5, pady=8, padx=5)

# 第2行

ft = tkFont.Font(family='楷体', size=38, weight=tkFont.BOLD)

label22 = tkinter.Label(root,

width=17,

height=5,

bg='DarkGray',#DarkSeaGreen DarkGray

fg='black',

justify='left',

relief='sunken',

font=ft) #wraplength=120,

label22.grid(row=2, column=1, rowspan=3, columnspan=4, sticky='NW')

# 第3行

pic_31 = tkinter.PhotoImage(file='pic/one11.png')

bt31 = tkinter.Button(root,

text='读单词',

width=60,

image=pic_31,

command=read_one)

bt31.grid(row=2, column=5, padx=15)

pic_32 = tkinter.PhotoImage(file='pic/all11.png')

bt32 = tkinter.Button(root,

text='读整段',

width=60,

image=pic_32,

command=read_all)

bt32.grid(row=3, column=5, padx=15)

pic_33 = tkinter.PhotoImage(file='pic/tx1.png')

bt33 = tkinter.Button(root,

text='听写',

width=60,

image=pic_33,

command=dictation)

bt33.grid(row=4, column=5, padx=15)

ft2 = tkFont.Font(family='Fixdsys', size=8)

label8 = tkinter.Label(root,

text='版本: bmy-001',

width=20,

font=ft2)

label8.grid(row=5, column=5)

s1 = tkinter.Scale(root,

label='音调',

from_=0,

to=10,

orient=tkinter.HORIZONTAL,

length=200,

showvalue=0,

tickinterval=10,

resolution=1)

s1.grid(row=5, column=1, columnspan=2, padx=15)

s1.set(5)

s2 = tkinter.Scale(root,

label='语速',

from_=0,

to=10,

orient=tkinter.HORIZONTAL,

length=200,

showvalue=0,

tickinterval=10,

resolution=1)

s2.grid(row=5, column=3, columnspan=2, padx=15, pady=1, sticky='N')

s2.set(5)

v = tkinter.IntVar()

boy = tkinter.PhotoImage(file='pic/男1.png')

tkinter.Radiobutton(

root,

text='男声',

variable=v,

image=boy,

value=1,

).grid(row=2, column=0, sticky='S')

girl = tkinter.PhotoImage(file='pic/女1.png')

tkinter.Radiobutton(

root,

text='女声',

variable=v,

image=girl,

value=0,

).grid(row=3, column=0)

v.set(0)

photo = tkinter.PhotoImage(file="./pic/古代儿童.png") # file:t图片路径

imgLabel = tkinter.Label(root, image=photo)

imgLabel.grid(row=4, column=0, rowspan=2, sticky='S')

root.mainloop()

六、预留功能:随时暂停播放过程的功能暂未设置,因为用生涩的底层控制代码去实现一个普通不过的mp3文件暂停播放功能,感觉性价比真的好差,所以......

二、Python3.7+Yolo3实现识别语音播报功能

这篇文章主要介绍了Python3.7 + Yolo3识别语音播报功能,开始之前我们先得解析出来Yolo3的代码,从而获取到被识别出来的物体标签,具体详细过程跟随小编一起看看吧

一、利用Python调用系统win10的文字转语音

私信小编01即可获取大量Python学习资源

首先下载需要用到的库:

pip install pyttsx3 -i https://mirrors.aliyun.com/pypi/simple/

接下来直接上代码:

import win32com.client as win

# SpVoice类是支持语音合成(TTS)的核心类。通过SpVoice对象调用TTS引擎,从而实现朗读功能

speak = win.Dispatch("SAPI.SpVoice")

# 完成将文本信息转换为语音并按照指定的参数进行朗读。

# 该方法有Text和Flags两个参数,分别指定要朗读的文本和朗读方式(同步或异步等)。

speak.Speak("come on")

speak.Speak("你好")

最后运行代码,就会听到系统传出来的声音,读出了 come on 和 你好。

二、开始使用Yolo识别,利用语音播报返回出来

开始之前我们先得解析出来Yolo3的代码,从而获取到被识别出来的物体标签。

首先我们找到一个coco_classes.txt,发现里面有很多的英文单词,这些就是准备识别匹配的标签了。

然后我们在找到yolo.py,发现的我们的coco_classes.txt被传入进来了

关键的来了,我们通过Ctrl + F 搜索一下classes_path这个Key,发现这几行代码

这里就是读取了存放标签的那个文本,进行了处理,并且返回了名字。

最后找到这一行代码,此处代码就是一开始进行识别的时候,我们的控制台打印出来的代码。

运行代码的时候发现,打印的这个label,就是识别出的物体的标签了。

这个时候我们就可以将我们的语音播报的代码添加进行,把label传入进去,就会发现识别出来的物体就会通过语音返回。


三、Python音频转换文字

  • 视频提取音频
  • 音频频率转化、音频切割
  • 音频转成文字

1视频提取音频

如果你练习时是录的视频,那需要将视频里的语音提取出来,方便后期操作

当然这个过程目前在各个视频剪辑软件里都可以一键分割,例如剪映、必剪、Pr等等

但是当任务量增加的时候,操作就显得非常浪费时间,而用Python的话3行代码就可以提取出来,就算任务量增加最多再加个循环即可

代码如下

from moviepy.editor import AudioFileClip
# 导入视频
my_audio_clip = AudioFileClip("一行玩Python/1012 视频转文字/11.mp4")
# 提取音频并保存
my_audio_clip.write_audiofile("一行玩Python/1012 视频转文字/11.wav")

2音频转文字

提取音频之后就要把音频转成文字了,目前市面上有很多方式都可以快速的将视频里的音频内容转成文字

  • 科大讯飞、知意等付费平台
  • 剪映、Pr等剪辑如案件生成字幕
  • 百度云、腾讯云等国内接口
  • GOogle、IBM、Bing等国外接口
  • 自己造轮子,语音识别训练
  • 自己一边听一边打字

虽然说有这么多方法可以去实现这个需求,但任务量增长后,想不花钱,又想不花时间造轮子,最好的办法就是用现成的接口

百度接口使用

申请百度接口

如果想用百度接口来批量处理,需要

百度语音API地址:https://cloud.baidu.com/doc/SPEECH/index.html

from aip import AipSpeech

""" 你的 APPID AK SK """
APP_ID = 'xxx'
API_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxx'
SECRET_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxx'

client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)

# 读取文件
def get_file_content(file_path):
    with open(file_path, 'rb') as fp:
        return fp.read()

# 识别本地文件
result = client.asr(get_file_content('音频.wav' % i), 'wav', 16000, {
    'dev_pid': 1537  # 默认1537(普通话 输入法模型),dev_pid参数见本节开头的表格
})

print(result['result'])

如果你恰巧是用mac录的音频,那就得对音频进行降频处理

因为百度接口只能识别16 kHz的音频,而mac录的是48 kHz的音频,当然用ffmpeg重采样一下就可以

import ffmpeg
ffmpeg.input('输入音频.wav').output('输出音频.wav', ar=16000).run()

如果的你音频比较长,但是百度短语音识别接口支持1分钟以内的音频,这时候需要对音频进行分割处理

from pydub import AudioSegment
from pydub.utils import make_chunks

#blues文件30s
audio = AudioSegment.from_file("voice.wav", "wav")

size = 30000  #切割的毫秒数

chunks = make_chunks(audio, size)  ##将文件切割为59s一块

for i, chunk in enumerate(chunks):
    ##枚举,i是索引,chunk是切割好的文件
    chunk_name = "voice{0}.wav".format(i)
    print(chunk_name)
    ##保存文件
    chunk.export(chunk_name, format="wav")

然后重采样、剪切好的音频循环调用百度API接口就可以完成了~

exe

当然,也有前辈利用百度API直接写成了一个exe来使用

只需要在刚才百度智能云注册申请账号即可使用

相关推荐

攀升战境S5电竞主机评测:NVIDIA RTX 3060实力助阵,光追游戏走起

此次笔者将为玩家们推荐一款游戏主机——攀升战境S5。该主机是攀升电脑今年力推的游戏装备,主机采用一线品牌配件,特别是在显卡选用上严苛把关,精选GeForceRTX30系列显卡,玩家们大可以放心选购...

慎买-神牛闪光灯兼容性问题:神牛V350&松下S5M2

神牛V350和松下S5M2的兼容性问题。大家好,我是向往闪光灯人像的Fish。国庆期间,我购买了神牛V350闪光灯和神牛X2T引闪器,但这成为了我的噩梦。我原以为客服和松友们说这款闪光灯在松下S5M2...

Acer蜂鸟持续办公一整天(acer 蜂鸟s5)

移动办公在工作节奏日益加快的今天越来越普遍,目前大部分工作无法在手持设备上完成,笔记本依然是移动办公最明智的选择。为了实现移动办公,很多笔记本越做越轻薄,性能也越来越强,而续航却一直没有很大提升。笔者...

职业车手明年会骑什么?2021赛季各大世巡赛车队使用器材一览

新年的钟声即将敲响,意味着充满魔幻色彩的2020年即将过去。受新冠肺炎的影响,2020年的赛季非常不同寻常。因这一原因不得不延迟举行的各种比赛导致许多车队的赞助商无法得到足够曝光,这也间接导致了许多车...

三星部分手机系统升级路线图流出(三星系统在哪升级)

三星包括Note3和S5在内的手机在升级到4.4.2系统之后一直没有什么系统升级的消息,而最近流出的一张三星的系统升级路线图中出现了一共13台手机升级KTU84P(也就是Android4.4.4)...

索尼Xperia Z3配置大曝光:升级并不大

IT之家(www.ithome.com):索尼XperiaZ3配置大曝光:升级并不大索尼明天就会在IFA2014大会上发布其下代旗舰XperiaZ3智能手机,目前网上曝光了其原型机,并且机身背后...

不进反退 三星Exynos 5433只能运行32位模式?

三星GalaxyNote4将带有两个版本,除了国行使用的骁龙805以外,还有三星自家的Exynos5433版本。而这颗SoC的详细信息三星并没有公布,据外媒Anandtech称,他们从源码中确认...

尼康Z6III测评:对比EOS R6 II、A7M4、S5IIX

摄影器材测评网站DPReview刚刚发布了尼康Z6III的完整图文测评,该机获得金奖评级,得分达到91%。以下是该文章的摘录——尼康Z6III核心规格:2400万像素“部分堆栈式”传感器RAW连拍:机...

赛默飞Ion S5首批数据公布,玩爆前任PGMTM系列

北美时间9月1日,赛默飞发布了两款最新的NGS系统IonS5和IonS5XL,旨在提供更加简捷的靶向测序流程。10月29日IonS5测序仪的首批实验数据产生于阜外医院。阜外医院研究人员选用了主...

Excel技巧:快速制作批量文件夹,省时省力,加强工作效率

大家好,如果公司领导要求按人员姓名制作文件夹,以一人一档的形式呈现人员档案,办公人员一个一个制作费时费力,而且效力低下,今天为大家介绍快捷制作批量文件夹的方法下面我们用图片来进行演示操作打开表格,选...

国行、港版、美版Apple watch各版本售价一览

今天凌晨,苹果牌手表正式发布,苹果开始正式进入可穿戴设备领域,除了功能和外观,我相信大家更关心的是价格问题了,小编就将国行、港版、美版的Applewatch售价做一总结,以供参考。国行:美版:港版:...

松下全画幅微单S5和S1到底哪里不一样?

Hello,我是ET,欢迎大家来到我的“相机笔记”。————9月2日晚,松下正式发布了第4款全画幅微单LUMIXS5。这一篇,我们主要来说松下LUMIXS5和LUMIXS1到底有哪些区别...

融会贯通之典范 神舟S7-2021S5评测

便携、性能、续航,这简简单单的六个字道出了这么些年来笔记本电脑的设计方向,可是由于底层技术、模具设计等等原因,这三点并不能很好的融合在一起。虽说闻道有先后,术业有专攻,但能够有一台融会贯通的产品,不是...

三国志战略版:S5赛季装X指南,开荒不是一成不变,需要因地制宜

大家好我是零氪玩家花席,S5赛季已经开始,因为S5赛季的野地阵容和S4赛季没有区别,所以S5赛季开荒相对不难。你在S4有经验,并且多了很多武将和战法,还能用150赛季功勋兑换7500战法点。S5赛季新...

聊聊松下S5M2和S5M2X的区别(松下s5k和s5c有什么区别)

先简单说下哪里不同:12bitRAWHDMI外录支持直接将视频录制到USB-SSD上多了All-Intra和ProRes编码支持有线/无线IP推流,USB网络连接黑化的机身不过要特别强调一下,S5...