现代生活中,我们不可避免会遇到很多碎片时间,等公交、倒地铁、排核酸、买早点等等。这些时间累积起来,无疑是一笔很大的个人资源,而想利用这部分时间,听显然是最好的方式。
国内云计算语音合成服务已经非常成熟,基于开源工具整合 TTS PaaS 服务,可以非常方便地打造一款个人定制的有声书制作工具。
好了,需求有了,可行性也没问题,开始搞起!Get hands dirty!
一、分析调研
有声书需求,一句话来讲就是,把电子书制作成有声音音频,并提供下载链接。
先细化下需求,拆解成不同过程,以及看看都需要哪些能力来支持:
- 我们根据个人喜好,下载好电子书(商用务必确保已获授权)。由于我之前用 Kindle,手上有大量 mobi 的电子书。
- 打开制作工具,上传指定的 mobi 电子书。(调研 Web 交互库)
- 制作工具需要先解析 mobi,获取其中的文本内容。(调研 mobi 解析库)
- 基于文本内容,调用语音合成服务,获取有声书音频内容。(调研云计算语音合成 PaaS 服务)
- 提供有声书音频下载。
经过一番调研,准备使用工具栈如下。
二、代码开发
工具栈到位,开始编码。
第一步:电子书文件解析
解析模块,先引入外部库 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 类,详见