学习
实践
活动
专区
工具
TVP
写文章
专栏首页腾讯云AI最佳实践!用腾讯云AI语音合成打造自己的第一本有声书
原创

最佳实践!用腾讯云AI语音合成打造自己的第一本有声书

现代生活中,我们不可避免会遇到很多碎片时间,等公交、倒地铁、排核酸、买早点等等。这些时间累积起来,无疑是一笔很大的个人资源,而想利用这部分时间,听显然是最好的方式。

国内云计算语音合成服务已经非常成熟,基于开源工具整合 TTS PaaS 服务,可以非常方便地打造一款个人定制的有声书制作工具。

好了,需求有了,可行性也没问题,开始搞起!Get hands dirty!

一、分析调研

有声书需求,一句话来讲就是,把电子书制作成有声音音频,并提供下载链接。

先细化下需求,拆解成不同过程,以及看看都需要哪些能力来支持:

  1. 我们根据个人喜好,下载好电子书(商用务必确保已获授权)。由于我之前用 Kindle,手上有大量 mobi 的电子书。
  2. 打开制作工具,上传指定的 mobi 电子书。(调研 Web 交互库)
  3. 制作工具需要先解析 mobi,获取其中的文本内容。(调研 mobi 解析库)
  4. 基于文本内容,调用语音合成服务,获取有声书音频内容。(调研云计算语音合成 PaaS 服务)
  5. 提供有声书音频下载。

经过一番调研,准备使用工具栈如下。

二、代码开发

工具栈到位,开始编码。

第一步:电子书文件解析

解析模块,先引入外部库 mobi,通过 mobi.extract 函数读取电子书文件,解析为 html 格式的文件 tmp_html。

mobi 库使用可以参见文档 mobi - library for unpacking mobi files

import mobi
def load_file(self, file_name):
        logging.info('begin to parse file')
        start_t = time.time()
        tmp_dir, tmp_html = mobi.extract(file_name) # 解析 mobi 文件
        end_t = time.time()
        logging.info('extract {} to {}. cost {}ms'.format(file_name, tmp_html, int((end_t-start_t)*1000)))

        with open(tmp_html, 'r') as fp:
            lines = fp.readlines()
        self.html_content = ''.join(lines) # 读取 html 
        logging.info('load file total {} chars'.format(len(self.html_content)))

        shutil.rmtree(tmp_dir)
        logging.info('clean temp dir {}'.format(tmp_dir))

得到 html 文件后,通过 lxml.etree 将其解析为一棵 DOM 树,然后就可以通过 xpath 这个大杀器,可以得到其中想要的任意内容了。

比如特定属性的元素,特定位置的段落、标题等等,不了解的同学可以看下 XPath教程

from lxml import etree
def parse_html(self):
        logging.info('parse html')
        # pre process
        self.html_content = self.pre_process(self.html_content)
        
        # parse dom
        dom = etree.fromstring(self.html_content)
        plist = dom.xpath('//p/text()')
        audio_texts = []

		# 示例,比如从 1010 段开始,获取后面 10 个段落
        idx_start = 1010
        for p in plist[idx_start:idx_start+10]:
            #logging.info('{}'.format(p))
            audio_texts.append(p)
        
        self.text = ''.join(audio_texts)
        logging.info('content length {}'.format(len(self.text)))

以上就是电子书解析模块,封装在 AudioBookGenerator 类,详见 src/audio_book_generator.py

第二步:有声语音合成

有声语音合成,需要基于第三方的语音合成 TTS 服务。调研了市面上常见云计算厂商 PaaS 服务后,决定采用腾讯云 TTS 服务。

我觉得比较好的点有三个

  1. 开发文档是基于开发者视角的,看起来非常顺畅。
  2. 长文本合成接口最长支持 10 万字,可以完整合成一个章节,适合合成有声书的场景,不用频繁拆分文本。
  3. 其中的智逍遥音色,以及旁对白支持的能力,适合小说场景;尤其是其中包含人物对话,旁白和对白分开后层次分明。

关于服务注册开通,官方文档写的很详细,就不赘述了,大家可以参见 腾讯云TTS

服务开通后,在控制台打开 API 密钥管理页面,拷贝如下的访问密钥,配置到 config 文件中即可。

配置文件 src/config.py

class Config(object): SECRET_ID = 'XXXX' # 对应上面的 SecretId SECRET_KEY = 'XXXX' # 对应上面的 SecretKey

下面看看怎么使用官网提供的 SDK ,调用语音合成服务。

打开 长文本合成官方开发文档,滚动下下面,找到对应的 sdk,这里我们用 python sdk

集成 SDK 到我们的工程。

长文本合成是个异步服务,提供两个接口用于服务调用。

  1. 创建合成任务接口:CreateTtsTask
  2. 查询任务状态及结果接口:DescribeTtsTaskStatus

下面的 create_task 函数和 query_task 函数,分别针对这两个函数进行了封装。

需要注意的是,查询任务状态时,任务可能并未执行完成,所以需要间隔一段时间后循环查询,直到任务完成(成功或失败)。

创建任务:CreateTtsTask

调用时,要注意两个参数

  • VoiceType:音色 id,用于选择不同的发音人,这里使用之前调研时确定的智逍遥(100510000),感觉非常适合武侠或玄幻小说的场景
  • VoiceoverDialogueSplit:旁对白支持选项,需要设置为 True,可以将文本中的对话和旁白分割,并分别用对应的音色进行合成

请求成功后,返回该任务的唯一 ID:TaskId

def create_task(self) -> str:
        task_id = ''

        req = models.CreateTtsTaskRequest()
        req.Text = self.text # 合成文本
        req.VoiceType = self.voice_type # 设置音色id,此处选用 智逍遥100510000
        req.VoiceoverDialogueSplit = self.voiceover_dialogue_split # 打开旁对白支持
        req.Codec = self.codec
        req.SampleRate = self.sample_rate
        req.ModelType = self.model_type
        try:
            resp = self.client.CreateTtsTask(req)
            task_id = resp.Data.TaskId
            req_id = resp.RequestId
            print('call CreateTtsTask succeed, task_id: {} request_id: {}'.format(task_id, req_id))
        except TencentCloudSDKException as err:
            print('call CreateTtsTask failed, err: {}'.format(str(err)))
        
        return task_id

查询任务状态及结果:DescribeTtsTaskStatus

调用是,将上面得到的 TaskId 作为参数传进去,请求会实时返回任务的相关信息,主要包含

  • Status:任务状态
  • ErrorMsg:任务错误信息(任务失败时)
  • ResultUrl:合成音频地址
def query_task(self, task_id):
        req = models.DescribeTtsTaskStatusRequest()
        req.TaskId = task_id
        try:
            resp = self.client.DescribeTtsTaskStatus(req)
            data = resp.Data
            req_id = resp.RequestId
            print('call DescribeTtsTaskStatus succeed, data: {} request_id: {}'.format(str(data), req_id))
        except TencentCloudSDKException as err:
            print('call DescribeTtsTaskStatus failed, err: {}'.format(str(err)))

        if data:
            return data.Status, data.ErrorMsg, data.ResultUrl # 任务状态、错误信息、音频文件地址
        else:
            return 3, 'internal error', ''

以上就是有声书语音合成模块,封装在 TencentSDK 类,详见 src/tencent_sdk.py

第三步:完成有声书制作脚本

通过 main 脚本,将上两步的电子书解析模块、语音合成模块集成到一起,再增加文件下载功能,即可完成有声书制作脚本。

腾讯云 TTS 服务返回的合成音频 url,新增 HttpAgent 类,将音频二进制文件下载到本地。

from audio_book_generator import AudioBookGenerator
from http_agent import HttpAgent

def main():
    file_name = sys.argv[1]
    logging.info('upload file: {}'.format(file_name))

    # gen audio
    generator = AudioBookGenerator()
    generator.process(file_name)
    audio_url = generator.get_audio_url()
    logging.info('get audo url: {}'.format(audio_url))
    
    # download audio
    session_path = os.environ.get('SESSION_PATH', './')
    audio_name = os.path.join(session_path, 'result.mp3')
    agent = HttpAgent()
    agent.download(audio_url, audio_name)
    logging.info('download audio to: {}'.format(audio_name))

HttpAgent 详见文件 src/http_agent.py

本地工具已完成,可以通过下列命令调用看下效果。

(venv) justin@VM_centos:[~/audio_book/src]: python main.py ../dou.mobi 
2022-06-21 10:36:44,959 - main.py[line:13] - INFO: upload file: ../dou.mobi
2022-06-21 10:36:44,959 - /home/justin/audio_book/src/audio_book_generator.py[line:26] - INFO: begin to parse file
2022-06-21 10:36:47,253 - /home/justin/audio_book/src/audio_book_generator.py[line:30] - INFO: extract ../dou.mobi to /tmp/mobiexk287bwzw/mobi7/book.html. cost 2294ms
2022-06-21 10:36:47,293 - /home/justin/audio_book/src/audio_book_generator.py[line:35] - INFO: load file total 4988080 chars
2022-06-21 10:36:47,295 - /home/justin/audio_book/src/audio_book_generator.py[line:38] - INFO: clean temp dir /tmp/mobiexk287bwzw
2022-06-21 10:36:47,295 - /home/justin/audio_book/src/audio_book_generator.py[line:45] - INFO: parse html
2022-06-21 10:36:47,506 - /home/justin/audio_book/src/audio_book_generator.py[line:60] - INFO: content length 625
2022-06-21 10:36:47,549 - /home/justin/audio_book/venv/lib64/python3.6/site-packages/urllib3/connectionpool.py[line:1005] - DEBUG: Starting new HTTPS connection (1): tts.tencentcloudapi.com:443
2022-06-21 10:36:47,699 - /home/justin/audio_book/venv/lib64/python3.6/site-packages/urllib3/connectionpool.py[line:465] - DEBUG: https://tts.tencentcloudapi.com:443 "POST / HTTP/1.1" 200 125
2022-06-21 10:36:47,701 - /home/justin/audio_book/venv/lib64/python3.6/site-packages/tencentcloud/common/http/request.py[line:112] - DEBUG: GetResponse Status: 200
Header: Server: nginx
Date: Tue, 21 Jun 2022 02:36:41 GMT
Content-Type: application/json
Content-Length: 125
Connection: keep-alive
Data: {"Response":{"RequestId":"ffb6f632-bd56-427d-ae21-xxxx","Data":{"TaskId":"gz-27ac44ab-c21e-4e58-b0b3-xxxx"}}}

call CreateTtsTask succeed, task_id: gz-27ac44ab-c21e-4e58-b0b3-xxxx request_id: ffb6f632-bd56-427d-ae21-xxxx

2022-06-21 10:37:27,964 - /home/justin/audio_book/venv/lib64/python3.6/site-packages/urllib3/connectionpool.py[line:1005] - DEBUG: Starting new HTTPS connection (1): tts.tencentcloudapi.com:443
2022-06-21 10:37:28,016 - /home/justin/audio_book/venv/lib64/python3.6/site-packages/urllib3/connectionpool.py[line:465] - DEBUG: https://tts.tencentcloudapi.com:443 "POST / HTTP/1.1" 200 576
2022-06-21 10:37:28,017 - /home/justin/audio_book/venv/lib64/python3.6/site-packages/tencentcloud/common/http/request.py[line:112] - DEBUG: GetResponse Status: 200
Header: Server: nginx
Date: Tue, 21 Jun 2022 02:37:21 GMT
Content-Type: application/json
Content-Length: 576
Connection: keep-alive
Data: {"Response":{"RequestId":"7c4c20d3-ad79-47ea-86a8-xxxx","Data":{"TaskId":"gz-27ac44ab-c21e-4e58-b0b3-xxxx","Status":2,"StatusStr":"success","ResultUrl":"https://xxxx","ErrorMsg":""}}}

call DescribeTtsTaskStatus succeed, data: {"TaskId": "gz-27ac44ab-c21e-4e58-b0b3-xxxx", "Status": 2, "StatusStr": "success", "ResultUrl": "https://xxxx", "ErrorMsg": ""} request_id: 7c4c20d3-ad79-47ea-86a8-xxxx
2022-06-21 10:37:28,580 - /home/justin/audio_book/venv/lib64/python3.6/site-packages/urllib3/connectionpool.py[line:465] - DEBUG: https://xxxx:443 "GET /xxxx HTTP/1.1" 200 535248
http download succ: https://xxxx -> ./result.mp3
2022-06-21 10:37:29,001 - main.py[line:26] - INFO: download audio to: ./result.mp3

可以正常生成音频文件 result.mp3。附录中有一个 demo 音频,大家可以听下,效果蛮不错。

第四步:脚本可视化

有声书制作脚本已完成,但脚本用起来还是不方便,而且没办法给他人使用。

这里需要对脚本进行可视化,将其部署为一个 Web 工具。

这里采用 Wooey 开源库,有如下优点:

  • 通过编译一个适配类,将脚本工具非常方便地转化为 Web 交互页面
  • 支持常见UI交互组件,如下拉框、文件上传等,通过代码配置的方式展示到页面上,无需任何前端知识
  • 支持任务启动、回显执行过程,结果文件下载等功能

适配类如下,通过 parseer 增加了文件上传组件

import os
import sys
import argparse

parser = argparse.ArgumentParser(description="convert mobi file to audio")
parser.add_argument('--audio', help='the mobi file to make audio', type=argparse.FileType('r'), required=True) # 文件上传组件

def audio_book(mobi_file):
    _format = mobi_file.split('.')[-1].lower()
    if _format != 'mobi':
        print('only mobi is supported')
        return
    
    # TODO: 此处填写业务逻辑

if __name__ == '__main__':

    args = parser.parse_args()
    audio_book(args.audio.name)

调用电子书制作脚本工具,通过 python venv 方式,隔离 wooey 与 工具脚本的环境变量,方便 wooey 平台集成其他任意脚本。

SCRIPT_PATH = '/root/audio_book'

def audio_book(mobi_file):
    # ...
    # TODO: 此处填写业务逻辑
    cmd = []
    cmd.append('export SESSION_PATH={}'.format(os.getcwd())) # 传输本次执行 session 路径到脚本
    cmd.append('cd {}'.format(SCRIPT_PATH))
    cmd.append('source {}/venv/bin/activate'.format(SCRIPT_PATH))
    cmd.append('cd src')
    cmd.append('python main.py {}'.format(mobi_file))
    cmd.append('cd ')
    cmd = '&&'.join(cmd)

    print(cmd)
    os.system(cmd)

添加脚本到可视化平台

[root@VM-centos ~/TOOLS]# python manage.py addscript ../audio_book/audio_book_adaptor.py --group 小工具 Converting ../audio_book/audio_book_adaptor.py Converted 0 scripts

所有工作已完成,让我们 enjoy 下效果。

三、产品体验

合成自己的第一本有声书

打开工具平台,选择有声书制作工具

点击【选择文件】按钮,上传想要转换的电子书文件

启动任务,从页面可以看到脚本执行日志

任务执行结束后,状态显示成功,可以从页面底部的文件列表中,点击 result.mp3 进行下载。

到此,整个有声书制作工具已经完成,试听音频以及工程代码放在附录中。

关于有声书的效果,感兴趣的同学可以从附录下载听下,个人觉得还蛮不错。

工程代码部分,基本上是开箱可用的,感兴趣的可以下载下来跑一下,也可以基于此增加自己需要的一些 feature。

好了,那就到这里 ~~

附录

了解更多腾讯云AI语音合成产品信息:语音合成_语音定制_文本转语音服务 - 腾讯云

原创声明,本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

登录 后参与评论
0 条评论

相关文章

  • 最佳实践|用腾讯云AI图像搜索打造属于自己的拍立淘

    最近,在一个论坛交流会上, 有嘉宾提出自己运营多年的微信小程序商城经常收到用户反馈:自己在逛街时候发现别人穿的好看的衣服,很难通过关键字定位到具体的商品,如果能...

    腾讯云AI
  • AI 专题用户实践征文

    2. 投稿内容必须保证内容原创性,实践过程真实、内容代码化,一经发现侵权行为,取消活动参与资格。

    腾讯云文档
  • 最佳实践 | 用腾讯云AI语音识别零基础实现小程序语音输入法

    先回顾下,生活、工作中你使用过哪些语音识别相关的产品或者服务? 培训/考试相关的小程序,使用语音识别来判断回答是否正确; 英语口语练习的小程序,使用语音识别来打...

    腾讯云AI
  • 腾讯云AI牵头制定2项计算机视觉标准

    6月30日,中国电子工业标准化技术协会正式发布《人工智能 深度合成图像系统技术规范》《人工智能 智能字符识别技术规范》《人工智能 视频图像审核系统技术规范》等3...

    腾讯云AI
  • 高保真音色媲美真人,StyleTTS为QQ浏览器「听书」语音注入情感

    今年 4 月,QQ 浏览器宣布 「小说频道」正式变更为 「免费小说」频道,这意味着阅文平台旗下的万千小说将免费供用户阅读。网络文学已浮浮沉沉二十余载,其阅读方式...

    机器之心
  • 【玩转腾讯云】征文活动获奖名单公布

    由云+社区联合腾讯云免费体验馆及各产品团队举办【玩转腾讯云】征文活动,吸引入驻作者积极参加,非常感谢各位作者的参与。经过评委老师从产品创新性、实用性、可借鉴性、...

    腾讯云开发者社区
  • 【腾讯云AI小程序大赛】中山大学作品《小耳朵天使》

    --------------------------------------------------------------------------------...

    陈华山
  • 观点 | 关于 AI 的应用与实践,腾讯 AI 研究员做了以下思考

    AI 科技评论按:由腾讯优图主办,腾讯云、腾讯 Ai Lab 和极客邦协办,主题为「智变未来-浅谈人工智能技术应用与实践」的技术沙龙活动 3 月 23 日在北京...

    AI科技评论
  • 当导航念出Rap范儿,有梗有味

    “主人,妲己开始为您导航;” “主人别急,这里可能被坦克堵住了;” “前方有限速摄像,限速80,疾跑技能请关闭。” “路漫漫其修远兮,路上不要玩手机;” “时刻...

    腾讯云AI
  • 【优秀最佳实践展播】第10期:腾讯云 AI

    腾讯云文档
  • 那些天籁之音,正在消亡

    你知道吗? 全球每2周就会有一种语言消失。 语言的消亡意味着珍贵的多样性文化信息流失,与物种的灭绝毫无二致。 现实情况是,濒危语言消亡的速度比濒危动物消亡的速...

    腾讯云AI
  • 谷歌文本转语音系统更新 可选择学习模型

    据外媒报道,近日,谷歌更新了其云端文本转语音(Cloud Text-to-Speech)API。

    IT派
  • 初音未来、洛天依、镜音......揭秘虚拟歌姬背后的大BOSS

    提到虚拟歌姬,你的第一反应是谁? 洛天依、初音未来、乐正绫、巡音、Gumi、言和、镜音、东方栀子......。(没上榜的记得评论区留言) 在二次元的世界里,虚拟...

    腾讯云AI
  • 腾讯云开发者社区技术沙龙资料合集

    腾讯云开发者社区技术沙龙
  • 直播预告 | 社交文娱赛道如何卷赢对手?

    移动互联网增长见顶已是一个公认的事实。 中国互联网络信息中心 (CNNIC)发布的《中国互联网络发展状况统计报告》显示,截至2021年12月,中国手机网民用户规...

    腾讯云AI
  • 大牛书单 | 世界读书日,TEG技术大牛为你荐书!

    腾讯技术工程官方号

扫码关注腾讯云开发者

领取腾讯云代金券