【Python】PC听书工具,微软tts朗读

简介:

使用edge-tts朗读txt文本。拥有“断点续读”的功能。会缓存一大堆的mp3文件,可以手动清理,也可以动手合成一个音频发b站之类的。: )

20230921更新:

为了避免缓存不够,听起来断断续续的,现在三线程同时下载音频……

源码:

# coding=utf-8
import json
import os.path
import threading
import time

import edge_tts as et
from playsound import playsound
import asyncio
"""
准备工作:
1、pip3 install edge_tts
2、pip3 install playsound
"""


def RTxt(path):
  with open(path, encoding='utf8') as f:
    return f.read()


def WTxt(path, content):
  with open(path, 'w', encoding='utf8') as f:
    f.write(content)


class Reader:
  def __init__(self, txtPath):
    self.novel = RTxt(txtPath)
    self.novelName = os.path.basename(txtPath).split('.')[0]
    self.lines = self.novel.split('\n')
    self.setting = {'pos': 0, 'downloadPos': 0}
    self.sayProcess = None
    if os.path.exists('setting.json'):
      self.setting = json.loads(RTxt('setting.json'))
    self.end = False

  def Start(self):
    def Download():
      while self.setting['downloadPos'] < len(self.lines):
        line = self.lines[self.setting['downloadPos']]
        try:
          self.Download(line)
        except Exception as e:
          print('Download.e=', e, self.setting['downloadPos'])
        WTxt('setting.json', json.dumps(self.setting))
        while self.setting['downloadPos'] > self.setting['pos'] + 300:
          time.sleep(1)

    def Say():
      while self.setting['pos'] < len(self.lines):
        while self.setting['downloadPos'] < self.setting['pos'] + 10:
          print('等待缓存中……')
          time.sleep(1)
        # print('下载行=', self.setting['downloadPos'])
        # print('朗读行=', self.setting['pos'])
        print('朗读行=', self.lines[self.setting['pos']], self.setting['pos'], self.setting['downloadPos'])
        self.Say()
        self.setting['pos'] += 1

    downloadThread = threading.Thread(target=Download, daemon=True)
    downloadThread.start()

    downloadThread2 = threading.Thread(target=Download, daemon=True)
    downloadThread2.start()

    downloadThread3 = threading.Thread(target=Download, daemon=True)
    downloadThread3.start()

    sayThread = threading.Thread(target=Say, daemon=True)
    sayThread.start()
    sayThread.join()

  def Download(self, text, voice='zh-CN-YunxiNeural', rate='+25%', volume='+0%'):
    mp3Path = 'temp\\{}_{}.mp3'.format(self.novelName, self.setting['downloadPos'])
    try:
      self.setting['downloadPos'] += 1

      async def Do():
        await t.save(mp3Path)
      t = et.Communicate(text=text, voice=voice, rate=rate, volume=volume)
      asyncio.run(Do())
    except Exception as e:
      print('[error]Download.e=', e, mp3Path)

  def Say(self):
    """朗读"""
    mp3Path = 'temp\\{}_{}.mp3'.format(self.novelName, self.setting['pos'])
    if os.path.exists(mp3Path) and os.path.getsize(mp3Path) > 0:
      try:
        playsound('{}\\{}'.format(os.getcwd(), mp3Path))
      except Exception as e:
        print('[error]Say.e=', e)


if __name__ == '__main__':
  reader = Reader('小说.txt')
  reader.Start()
  print('程序终止!')

暂停之类的功能实现起来比较麻烦,就没弄了。

你可能感兴趣的:(python)