一个资深小说迷打开小说的正确姿势(续)----百度AI文字转语音

前段时间闲得无聊,使用python抓取了自己想看的小说,抓取方法:一个资深小说迷打开小说的正确姿势
一个资深小说迷打开小说的正确姿势(续)----百度AI文字转语音_第1张图片
最近发现连续长时间盯着屏幕,眼睛实在是有点遭不住。对于我这种又想保护视力,又不想放下小说的人来说,简直就是遇到了像 “ 鱼与熊掌不可兼得” 一般的世纪难题。
一个资深小说迷打开小说的正确姿势(续)----百度AI文字转语音_第2张图片
正当我思考如何两害取其轻的时候,有人私信我帮忙做一个文字转语音的接口,我突然灵机一动,这简直就是送上门来的满分答案啊
一个资深小说迷打开小说的正确姿势(续)----百度AI文字转语音_第3张图片
当然,对于我这种社畜来说,是万万不可能自己实现文字转语音功能的,我没有那个精力,更没有那个 money
一个资深小说迷打开小说的正确姿势(续)----百度AI文字转语音_第4张图片
不过,咱不会煮饭,咱还不会点外卖么?O(∩_∩)O哈哈~
一个资深小说迷打开小说的正确姿势(续)----百度AI文字转语音_第5张图片
打开快被我点裂开了的 google chrome 搜了搜,果然很多公司都提供现成的免费接口,比如百度、讯飞…最后我选择了百度AI接口(这种东西啊,就和点外卖是一样的,同样都是芋儿鸡,店家不一样,做出来的味道就有好有坏。当你都没吃过时,牌子大一点的店或许是个不坏的选择)
一个资深小说迷打开小说的正确姿势(续)----百度AI文字转语音_第6张图片
言归正传,首先你得去百度控制台登录一下,没有百度账号的需要注册:
https://ai.baidu.com/tech/speech
一个资深小说迷打开小说的正确姿势(续)----百度AI文字转语音_第7张图片

然后需要创建一个应用,创建好了之后,就能拿到我们想要的三个东西
一个资深小说迷打开小说的正确姿势(续)----百度AI文字转语音_第8张图片
然后,python需要安装两个库(百度接口库和语音播放库),如果不需要python播放音频的话,只需要安装第一个库就行:

pip install baidu-aip
pip install playsound

根据百度提供的接口文档https://ai.baidu.com/ai-doc/SPEECH/Gk4nlz8tc,我们可以很容易的将一段文本翻译成音频文件,如:

from aip import AipSpeech	# 导入api接口
from playsound import playsound	# 音频模块

#对应填入百度控制台获取的三个参数
APP_ID = ''
API_KEY = ''
SECRET_KEY = ''
client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)

data = '你是最棒的,hello world'
result = client.synthesis(data, 'zh', 1, {
    'per': 4,
    'spd': 3,    # 速度
    'vol': 7   # 音量
})
if not isinstance(result, dict):
    with open('hello.mp3', 'wb') as f:
        f.write(result)

# 播放
playsound("hello.mp3")

上面这段代码,你只需要对应的填入百度后台获取的三个参数,然后运行文件,就会在你的代码文件同级目录下生成一个音频文件hello.mp3,并且会有美女夸你
一个资深小说迷打开小说的正确姿势(续)----百度AI文字转语音_第9张图片
有美女夸固然是好,可是我们最初的梦想是听小说啊。
一个资深小说迷打开小说的正确姿势(续)----百度AI文字转语音_第10张图片
别着急,你只需要将代码中的 data 内容换成咱们使用爬虫爬下来的小说内容,如:

#读取文本文件内容
    with open(file_name, 'r', encoding='utf-8') as f:
        data = f.read()

此时要注意,百度API每一次翻译的文本长度必须小于1024字节,小说每一章的内容往往大于1024字节,怎么办呢?
咱们可以将文本分割,然后多次请求就行了,写一个分割方法,像这样:

#按指定字节数分割字符串
def byte_split(seq):
    list = []
    while seq:
        if len(seq) >= 1024:
            list.append(seq[:1024])
            seq = seq[1024:]
        else:
            list.append(seq)
            seq = []
    return list

简单封装一下,第一版就出炉啦:

from aip import AipSpeech	# 导入api接口
from playsound import playsound	# 音频模块
import sys


#百度账号信息配置
#对应填入百度控制台获取的三个参数
APP_ID = ''
API_KEY = ''
SECRET_KEY = ''

client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)

#按指定字节数分割字符串
def byte_split(seq):
    list = []
    while seq:
        if len(seq) >= 1024:
            list.append(seq[:1024])
            seq = seq[1024:]
        else:
            list.append(seq)
            seq = []
    return list
 
'''
 @desc 写入音频
 
 @param data_arr list 文件数组
 @param vedio_name string 音频文件名
 
 @return 音频文件名
'''
def vedio_write(data_arr, vedio_name):
    name = vedio_name + '.mp3'
    for i in data_arr:
        #请求百度接口,获取语音二进制
        result = client.synthesis(i, 'zh', 1, {
            'per': 4,
            'spd': 3,    # 速度
            'vol': 7   # 音量
        })
        #判断是否翻译成功-成功则写入,失败则打印错误信息
        if not isinstance(result, dict):
            with open(name, 'ab') as f:
                f.write(result)
        else:
            print(result)
    return name    


#主函数
if __name__ == "__main__":
    #文本文件
    file_name = r'../novel/quanzhifashi/第1章 世界大变.txt'
    #音频文件名
    vedio_name = file_name.split('/')[-1].split('.')[0]
    

    #读取文本文件内容
    with open(file_name, 'r', encoding='utf-8') as f:
        data = f.read()

    #按字符串拆分成数组
    data_arr = byte_split(data) 
    
    #写入音频,返回音频文件名
    vedio = vedio_write(data_arr, vedio_name)     
    
    # 播放
    playsound(vedio)

点击运行,在我的保存目录找到了自己想要的结果
一个资深小说迷打开小说的正确姿势(续)----百度AI文字转语音_第11张图片
但是并没有给我播放视频,而且反手扔给我一个Error
一个资深小说迷打开小说的正确姿势(续)----百度AI文字转语音_第12张图片
查看报错信息发现,由于我的音频文件是中文名,所以播放失败了,将中文换掉就可以正常播放。

但是总有像我一样杠中带倔的人,喜欢将音频文件命名为中文,怎么办呢?当然是打开我那要裂开了的google chrome 啊。巡视了一圈,最后发现pygame库可以解决这个问题。好嘛,安装pygame库:

pip install pygame

封装个方法,使用pygame播放音频:

# 播放音频
# 貌似只能播放单声道音乐,可能是pygame模块限制
def playMusic(filename, loops=0, start=0.0, value=0.5):
    """
    :param filename: 文件名
    :param loops: 循环次数
    :param start: 从多少秒开始播放
    :param value: 设置播放的音量,音量value的范围为0.0到1.0
    :return:
    """
    flag = False  # 是否播放过
    pygame.mixer.init()  # 音乐模块初始化
    while 1:
        if flag == 0:
            pygame.mixer.music.load(filename)
            # pygame.mixer.music.play(loops=0, start=0.0) loops和start分别代表重复的次数和开始播放的位置。
            pygame.mixer.music.play(loops=loops, start=start)
            pygame.mixer.music.set_volume(value)  # 来设置播放的音量,音量value的范围为0.0到1.0。
        if pygame.mixer.music.get_busy() == True:
            flag = True
        else:
            if flag:
                pygame.mixer.music.stop()  # 停止播放
                break

再将之前的代码整合一下子,最终版本就出炉了:

from aip import AipSpeech	# 导入api接口
#from playsound import playsound	# 音频模块
import sys
import pygame


#百度账号信息配置
#对应填入百度控制台获取的三个参数
APP_ID = ''
API_KEY = ''
SECRET_KEY = ''

client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)

#按指定字节数分割字符串
def byte_split(seq):
    list = []
    while seq:
        if len(seq) >= 1024:
            list.append(seq[:1024])
            seq = seq[1024:]
        else:
            list.append(seq)
            seq = []
    return list
 
'''
 @desc 写入音频
 
 @param data_arr list 文件数组
 @param vedio_name string 音频文件名
 
 @return 音频文件名
'''
def vedio_write(data_arr, vedio_name):
    name = vedio_name + '.mp3'
    for i in data_arr:
        #请求百度接口,获取语音二进制
        result = client.synthesis(i, 'zh', 1, {
            'per': 4,
            'spd': 3,    # 速度
            'vol': 7   # 音量
        })
        #判断是否翻译成功-成功则写入,失败则打印错误信息
        if not isinstance(result, dict):
            with open(name, 'ab') as f:
                f.write(result)
        else:
            print(result)
    return name    

# 播放音频
# 貌似只能播放单声道音乐,可能是pygame模块限制
def playMusic(filename, loops=0, start=0.0, value=0.5):
    """
    :param filename: 文件名
    :param loops: 循环次数
    :param start: 从多少秒开始播放
    :param value: 设置播放的音量,音量value的范围为0.0到1.0
    :return:
    """
    flag = False  # 是否播放过
    pygame.mixer.init()  # 音乐模块初始化
    while 1:
        if flag == 0:
            pygame.mixer.music.load(filename)
            # pygame.mixer.music.play(loops=0, start=0.0) loops和start分别代表重复的次数和开始播放的位置。
            pygame.mixer.music.play(loops=loops, start=start)
            pygame.mixer.music.set_volume(value)  # 来设置播放的音量,音量value的范围为0.0到1.0。
        if pygame.mixer.music.get_busy() == True:
            flag = True
        else:
            if flag:
                pygame.mixer.music.stop()  # 停止播放
                break



#主函数
if __name__ == "__main__":
    #文本文件
    file_name = r'../novel/quanzhifashi/第1章 世界大变.txt'
    #音频文件名
    vedio_name = file_name.split('/')[-1].split('.')[0]
    

    #读取文本文件内容
    with open(file_name, 'r', encoding='utf-8') as f:
        data = f.read()

    #按字符串拆分成数组
    data_arr = byte_split(data) 
    
    #写入音频,返回音频文件名
    vedio = vedio_write(data_arr, vedio_name)     

    #音频播放
    playMusic(vedio)
    #playMusic('out.wav')
    
    # 播放
    #playsound(vedio)

谁说鱼与熊掌不可兼得?

The end !

一个人最好的生活状态,有自己的生活和情趣,努力完善自己。没人爱时专注自己,有人爱时,有能力拥抱彼此。

你可能感兴趣的:(Python)