Coder Social home page Coder Social logo

read_tts's Introduction

简单的听书音频生成

这是一个为阅读3制作的生成章节音频的程序。 由于作者能力,仅仅是CLI工具。 Sample

安装

拥有python环境和基础

  • 克隆当前存储库
  • 安装依赖: pip install -r requirment.txt
  • 下载ffmpeg.exe并保存在当前程序相同文件夹,或在path中设置.

没有python环境

  • 在最新的Release中下载main.exe
  • 下载ffmpeg.exe并保存在当前程序相同文件夹,或在path中设置.

用法

  • 在阅读app中打开Web 服务, 并且记录显示的ip地址。

get_ip

  • 运行这个程序, 并输入1.

intro

  • 输入记录的ip地址

ip

  • 输入书籍id

choose

  • 输入开始和结束的页面id,您可以在开始处留空,这意味着选择当前章节。提示格式: (<id>: <标题>). id有时会由于书源造成误差, 您可以根据开始章节的id数据计算这个误差。

book

  • 接着等待程序运行结束即可!

菜单

1. Basic

基础模式,您可以根据交互提示和上述内容使用。

2. Fix

如果你看见 Retry (for fix mode), 那么你便需要运行这个模式。这意味着某个章节的音频合成失败了太多次.(你可以通过MAX_RETRY修改这个数据) 你可以复制 Retry (for fix mode)后的数据并输入在提示中, 然后程序便会像标准模式运行。

3. Concat

如果你的程序意外退出, 那么文件夹中便会出现像 340_第xxx章xxx (1).mp3这样的文件。如果你遇到了这个情况,你可以运行这个模式自动修复这个错误。注意: 如果某个章节下载了部分,那么可能出现未知情况(通常出现于最后几个)

4. Delete temporary files

如果你在输出文件夹中发现340_第xxx章xxx (1).mp3或者控制台中有ERROR: _merge: Permission denied!,这是一个已知bug(还没调试明白,如果谁有思路,请麻烦提一下Issue). 你可以通过运行这个模式来修复。3

配置

你可以运行一次主程序,便会生成config.json,并附有默认配置。你可以修改,或者使用自定义json,这个json必须是原json的子集。程序会自动检查类型和key,在软件更新过程中,部分参数有删除或改动,软件会自动更新到最新参数。如果您确定您的json在老版可用但新版不可用,请在Github上提Issue。

名称 类型 默认 含义
MAX_RETRY int 5 重试次数最大值
MAX_TASK int 10 最大并行任务数
MAX_CHAR int 1500 单个音频最大字数, 你可以查看这个
WAIT_TIME int/float 5 两次重试间等待时间
RETRY_SUB int/float 2 当重试时,任务数会除以MAX_TASK1
MAX_WAIT int 20 最大等待时间2
TRANS_MODE int 2 转化模式:目前有效值为基础模式(1)、角色模式(2)4
TIMEOUT int/float 3 链接到app的超时值(单位:秒)
OPT_DIR int Output 输出文件夹
SHOW_DEBUG bool false 显示调试信息
SAVE_LOG bool true 保存日志信息
SAVE_REQ bool false 保存所有请求记录(用于反馈)
TO_CONSOLE bool true 在控制待中显示日志(包括INFO和ERROR信息)
LANG_FILE str zh 语言文件5
ip str app的ip(包含端口)

语言

目前已制作两种语言的语言数据,默认为英文,可以在config.json中的修改LANG_FILE。 目前已有lang_chk.py检验语言文件,但是运行方式过于草率,可能会出现安全问题,请仅用于已知来源文件!

运行模式

对于模式1:基础模式;对于模式2:角色模式。角色模式通过引号等常用符号标记角色语言内容,将该部分内容换为另一角色合成。

识别的符号

  • “文本”
  • "文本"
  • 【文本】
  • '文本'

自动回退

注:对于文章中出现以下情况,角色模式将自动回退到基础模式(将提示错误)。

  1. 文章中出现引号不匹配。如

文本“对话内容

  1. 文本中存在引号不配对的情况。如

文本对话内容。 其余内容“对话内容”

Notes

  1. 如果音频合成失败,程序会重试MAX_RETRY次。在重试后,同时运行的任务会除被以RETRY_SUB,并且等待WAIT_TIME秒。
  2. 我使用了aspeak模块来合成音频,但是只有一些限制。其中还有一个没有被记录的限制:不能短时间内合成多次。如果合成失败率大于LIMIT_429,并且完成(失败)了FAIL_429个音频,程序会等待正在运行的所有任务结束,然后等待9+3*stop_cnt。其中,变量stop_cnt是总失败次数,并且等待时间不会超过MAX_WAIT。如果超过,便会将等待时间固定为15s。
  3. 最后一个文件好像会被ffmpeg或者python进程占用,这似乎不是我的代码的问题,因为只有在windows平台上出现。
  4. 运行模式见上
  5. 内置语言文件zhen,对应源文件lang_zh.jsonlang_en.json,如果想要修改语言文件,请同时修改config中的LANG_FILE,即便文件名lang_zh.jsonzh也不行。

FAQ

Q: Showe text like "\033****" and so on

A: use cmder to run it, the console should support ANSI colorful output.

Q: Find file like <TiTle>(1)

A: Start main program again and run mode 4

Q: The program interrupted unexpectedly, but there are many <title>(1) in output folder

A: Start main program again and run mode 3

read_tts's People

Contributors

flt6 avatar

Watchers

 avatar

Forkers

yufeixuan coreult

read_tts's Issues

Tag over limited

                    DEBUG    code: CancellationErrorCode.RuntimeError                                                                                          utils.py:410
                    ERROR    RuntimeError:                                                                                                                     utils.py:416
┌─────────────────────────────── Traceback (most recent call last) ────────────────────────────────┐
│ C:\ProgramData\mambaforge-pypy3\envs\main\lib\site-packages\mytts\tts.py:87 in implete           │
│                                                                                                  │
│    84 │   │   end_resp_pat = re.compile('Path:turn.end')                                         │
│    85 │   │   audio_stream:bytes = b''                                                           │
│    86 │   │   while(True):                                                                       │
│ >  87 │   │   │   response = await websocket.recv()                                              │
│    88 │   │   │   if re.search(end_resp_pat, str(response)) is None:                             │
│    89 │   │   │   │   if type(response) == type(bytes()):                                        │
│    90 │   │   │   │   │   # print("recv ({}) {}".format(req_id,response[:5]))                    │
│                                                                                                  │
│ C:\ProgramData\mambaforge-pypy3\envs\main\lib\site-packages\websockets\legacy\protocol.py:568 in │
│ recv                                                                                             │
│                                                                                                  │
│    565 │   │   │   │   else:                                                                     │
│    566 │   │   │   │   │   # Wait until the connection is closed to raise                        │
│    567 │   │   │   │   │   # ConnectionClosed with the correct code and reason.                  │
│ >  568 │   │   │   │   │   await self.ensure_open()                                              │
│    569 │   │                                                                                     │
│    570 │   │   # Pop a message from the queue.                                                   │
│    571 │   │   message = self.messages.popleft()                                                 │
│                                                                                                  │
│ C:\ProgramData\mambaforge-pypy3\envs\main\lib\site-packages\websockets\legacy\protocol.py:953 in │
│ ensure_open                                                                                      │
│                                                                                                  │
│    950 │   │   │   # CLOSING state also occurs when failing the connection. In that              │
│    951 │   │   │   # case self.close_connection_task will complete even faster.                  │
│    952 │   │   │   await asyncio.shield(self.close_connection_task)                              │
│ >  953 │   │   │   raise self.connection_closed_exc()                                            │
│    954 │   │                                                                                     │
│    955 │   │   # Control may only reach this point in buggy third-party subclasses.              │
│    956 │   │   assert self.state is State.CONNECTING                                             │
└──────────────────────────────────────────────────────────────────────────────────────────────────┘
ConnectionClosedError: received 1007 (invalid data) SSML must contain a maximum of 50 voice elements. Actual 51.; then sent 1007 (invalid data) SSML must contain a maximum
of 50 voice elements. Actual 51.
                    ERROR    Traceback (most recent call last):                                                                                                utils.py:421
                               File "C:\ProgramData\mambaforge-pypy3\envs\main\lib\site-packages\mytts\tts.py", line 87, in implete
                                 response = await websocket.recv()
                               File "C:\ProgramData\mambaforge-pypy3\envs\main\lib\site-packages\websockets\legacy\protocol.py", line 568, in recv
                                 await self.ensure_open()
                               File "C:\ProgramData\mambaforge-pypy3\envs\main\lib\site-packages\websockets\legacy\protocol.py", line 953, in ensure_open
                                 raise self.connection_closed_exc()
                             websockets.exceptions.ConnectionClosedError: received 1007 (invalid data) SSML must contain a maximum of 50 voice elements.
                             Actual 51.; then sent 1007 (invalid data) SSML must contain a maximum of 50 voice elements. Actual 51.

                    DEBUG    Error                                                                                                                             utils.py:427
                    ERROR    原因: ResultReason.Canceled                                                                                                       utils.py:428
                    DEBUG    idx=233                                                                                                                           utils.py:430
                    ERROR    Async request error!                                                                                                          exceptions.py:90
                             RE: ret.reason=ResultReason.Canceled
                    DEBUG                                                                                                                                  exceptions.py:96
                             ┌──────────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────────┐
                             │ E:\***\utils.py:431 in _deal                                                               │
                             │                                                                                                                           │
                             │   428 │   │   │   │   │   logger.error(config.lang["utils"]                                                               │
                             │   429 │   │   │   │   │   │   │   │   ["ToSer"]["fail"] + str(ret.reason))                                                │
                             │   430 │   │   │   │   │   logger.debug("idx=%d" % chapters[j].idx)                                                        │
                             │ > 431 │   │   │   │   │   raise RuntimeError("ret.reason=%s" % ret.reason)                                                │
                             │   432 │   │   │   │   else:                                                                                               │
                             │   433 │   │   │   │   │   assert ret.audio_duration is not None, "Audio here should not be not                            │
                             │       available. All error should be catched below."                                                                      │
                             │   434 │   │   │   │   │   self.total_time += ret.audio_duration.total_seconds() / 60                                      │
                             └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
                             RuntimeError: ret.reason=ResultReason.Canceled
                    DEBUG    audio_duration=None

Chapter 404

Check if chapter text is 404 before running, because of the book source.

Can't download

Can't download
DEBUG - choose_book: bgn: 476 to: 489.
Downloaded files are 0 bytes, and the name is wrong.

Some connection error is uncaught

Error log file:

2022-05-13 20:54:23,746 - CRITICAL - <module>: An uncaught error occurred during Main.main
Traceback (most recent call last):
  File "C:\Users\dicp\AppData\Local\Temp\ONEFIL~4\websockets\protocol.py", line 827, in transfer_data
  File "C:\Users\dicp\AppData\Local\Temp\ONEFIL~4\websockets\protocol.py", line 895, in read_message
  File "C:\Users\dicp\AppData\Local\Temp\ONEFIL~4\websockets\protocol.py", line 971, in read_data_frame
  File "C:\Users\dicp\AppData\Local\Temp\ONEFIL~4\websockets\protocol.py", line 1047, in read_frame
  File "C:\Users\dicp\AppData\Local\Temp\ONEFIL~4\websockets\framing.py", line 133, in read
  File "C:\Users\dicp\AppData\Local\Temp\ONEFIL~4\asyncio\streams.py", line 723, in readexactly
  File "C:\Users\dicp\AppData\Local\Temp\ONEFIL~4\asyncio\streams.py", line 517, in _wait_for_data
asyncio.exceptions.CancelledError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\dicp\AppData\Local\Temp\ONEFIL~4\gather.py", line 114, in wait
  File "C:\Users\dicp\AppData\Local\Temp\ONEFIL~4\tts.py", line 105, in mainSeq
  File "C:\Users\dicp\AppData\Local\Temp\ONEFIL~4\tts.py", line 85, in transferMsTTSData
  File "C:\Users\dicp\AppData\Local\Temp\ONEFIL~4\websockets\protocol.py", line 509, in recv
  File "C:\Users\dicp\AppData\Local\Temp\ONEFIL~4\websockets\protocol.py", line 812, in ensure_open
websockets.exceptions.ConnectionClosedError: code = 1006 (connection closed abnormally [internal]), no reason

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\dicp\AppData\Local\Temp\ONEFIL~4\gather.py", line 221, in <module>
  File "C:\Users\dicp\AppData\Local\Temp\ONEFIL~4\gather.py", line 200, in main
  File "C:\Users\dicp\AppData\Local\Temp\ONEFIL~4\asyncio\runners.py", line 44, in run
  File "C:\Users\dicp\AppData\Local\Temp\ONEFIL~4\asyncio\base_events.py", line 642, in run_until_complete
  File "C:\Users\dicp\AppData\Local\Temp\ONEFIL~4\gather.py", line 185, in download
  File "C:\Users\dicp\AppData\Local\Temp\ONEFIL~4\gather.py", line 121, in wait
TypeError: can only concatenate list (not "int") to list

Cut at 10min

If mp3 length is over 10min, file will be cut.

The last one to generate failed to remove

ERROR: _merge: Permission denied!
DEBUG:
Traceback (most recent call last):
  File "E:\TEMP\git\git\Read_tts-web\Read_tts\utils.py", line 363, in _merge
    remove(path)
PermissionError: [WinError 32] 另一个程序正在使用此文件,进程无法访问。: 'Output/xxx_xxxxxxxx (1).mp3'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.