8 Commits
Author SHA1 Message Date
Deniz Şafak 033c809b95 Update changelog 2025-09-18 03:12:35 +03:00
Deniz Şafak f492cc2506 v1.1.9 2025-09-18 03:11:52 +03:00
Deniz Şafak 495a50f666 Merge branch 'main' of https://github.com/denizsafak/abogen 2025-09-18 03:09:04 +03:00
Deniz Şafak 8c6e292f4f Fixed markdown TOC generation 2025-09-18 03:08:30 +03:00
Deniz Şafak 1d8cb8eabd Fixed the issue where spaces were deleted before punctuation marks 2025-09-18 02:37:58 +03:00
Deniz ŞafakandGitHub a3ee95e83f Update readme 2025-09-18 01:50:28 +03:00
Deniz ŞafakandGitHub a98f75c1a9 Update readme 2025-09-17 23:07:36 +03:00
Deniz Şafak f4f3a4c207 Update readme 2025-09-17 22:39:45 +03:00
6 changed files with 53 additions and 27 deletions
+5
View File
@@ -1,3 +1,8 @@
# 1.1.9
- Fixed the issue where spaces were deleted before punctuation marks while generating subtitles.
- Fixed markdown TOC generation breaks when "Replace single newlines" is enabled.
- Improvements in code and documentation.
# 1.1.8 # 1.1.8
- Added `.md` (Markdown) file extension support by @brianxiadong in PR #75 - Added `.md` (Markdown) file extension support by @brianxiadong in PR #75
- Added new option `Configure silence between chapters` that lets you configure the silence between chapters, mentioned by @lfperez1982 in #79 - Added new option `Configure silence between chapters` that lets you configure the silence between chapters, mentioned by @lfperez1982 in #79
+34 -2
View File
@@ -7,6 +7,8 @@
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![License: MIT](https://img.shields.io/badge/License-MIT-maroon.svg)](https://opensource.org/licenses/MIT) [![License: MIT](https://img.shields.io/badge/License-MIT-maroon.svg)](https://opensource.org/licenses/MIT)
<a href="https://trendshift.io/repositories/14433" target="_blank"><img src="https://trendshift.io/api/badge/repositories/14433" alt="denizsafak%2Fabogen | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
Abogen is a powerful text-to-speech conversion tool that makes it easy to turn ePub, PDF, text or markdown files into high-quality audio with matching subtitles in seconds. Use it for audiobooks, voiceovers for Instagram, YouTube, TikTok, or any project that needs natural-sounding text-to-speech, using [Kokoro-82M](https://huggingface.co/hexgrad/Kokoro-82M). Abogen is a powerful text-to-speech conversion tool that makes it easy to turn ePub, PDF, text or markdown files into high-quality audio with matching subtitles in seconds. Use it for audiobooks, voiceovers for Instagram, YouTube, TikTok, or any project that needs natural-sounding text-to-speech, using [Kokoro-82M](https://huggingface.co/hexgrad/Kokoro-82M).
<img title="Abogen Main" src='https://raw.githubusercontent.com/denizsafak/abogen/refs/heads/main/demo/abogen.png' width="380"> <img title="Abogen Processing" src='https://raw.githubusercontent.com/denizsafak/abogen/refs/heads/main/demo/abogen2.png' width="380"> <img title="Abogen Main" src='https://raw.githubusercontent.com/denizsafak/abogen/refs/heads/main/demo/abogen.png' width="380"> <img title="Abogen Processing" src='https://raw.githubusercontent.com/denizsafak/abogen/refs/heads/main/demo/abogen2.png' width="380">
@@ -90,11 +92,13 @@ pip3 uninstall torch
pip3 install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/rocm6.4 pip3 install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/rocm6.4
``` ```
> See [How to fix "CUDA GPU is not available. Using CPU" warning?](#cuda-warning)
> See [How to fix "WARNING: The script abogen-cli is installed in '/home/username/.local/bin' which is not on PATH" error in Linux?](#path-warning) > See [How to fix "WARNING: The script abogen-cli is installed in '/home/username/.local/bin' which is not on PATH" error in Linux?](#path-warning)
> See [How to fix "No matching distribution found" error?](#no-matching-distribution-found) > See [How to fix "No matching distribution found" error?](#no-matching-distribution-found)
> See [How to fix "CUDA GPU is not available. Using CPU" warning?](#cuda-warning) > See [How to use "uv" instead of "pip"?](#use-uv-instead-of-pip)
> Special thanks to [@hg000125](https://github.com/hg000125) for his contribution in [#23](https://github.com/denizsafak/abogen/issues/23). AMD GPU support is possible thanks to his work. > Special thanks to [@hg000125](https://github.com/hg000125) for his contribution in [#23](https://github.com/denizsafak/abogen/issues/23). AMD GPU support is possible thanks to his work.
@@ -139,6 +143,7 @@ Heres Abogen in action: in this demo, it processes 3,000 characters of tex
| **Save location** | `Save next to input file`, `Save to desktop`, or `Choose output folder` | | **Save location** | `Save next to input file`, `Save to desktop`, or `Choose output folder` |
> Special thanks to [@brianxiadong](https://github.com/brianxiadong) for adding markdown support in PR [#75](https://github.com/denizsafak/abogen/pull/75) > Special thanks to [@brianxiadong](https://github.com/brianxiadong) for adding markdown support in PR [#75](https://github.com/denizsafak/abogen/pull/75)
> Special thanks to [@jborza](https://github.com/jborza) for chapter support in PR [#10](https://github.com/denizsafak/abogen/pull/10) > Special thanks to [@jborza](https://github.com/jborza) for chapter support in PR [#10](https://github.com/denizsafak/abogen/pull/10)
| Book handler options | Description | | Book handler options | Description |
@@ -318,7 +323,19 @@ abogen-cli.exe
This will start Abogen in command-line mode and display detailed error messages. Please open a new issue on the [Issues](https://github.com/denizsafak/abogen/issues) page with the error message and a description of your problem. This will start Abogen in command-line mode and display detailed error messages. Please open a new issue on the [Issues](https://github.com/denizsafak/abogen/issues) page with the error message and a description of your problem.
## `Tips and Solutions` ## `Common Issues & Solutions`
<details><summary><b>
<a name="about-abogen">About the name "abogen"</a>
</b></summary>
> The name **"abogen"** comes from a shortened form of **"audiobook generator"**, which is the purpose of this project.
>
> After releasing the project, I learned from [community feedback](https://news.ycombinator.com/item?id=44853064#44857237) that the prefix *"abo"* can unfortunately be understood as an ethnic slur in certain regions (particularly Australia and New Zealand). This was something I was not aware of when naming the project, as English is not my first language.
>
> I want to make it clear that the name was chosen only for its technical meaning, with **no offensive intent**. Im grateful to those who kindly pointed this out, as it helps ensure the project remains respectful and welcoming to everyone.
</details>
<details><summary><b> <details><summary><b>
<a name="cuda-warning">How to fix "CUDA GPU is not available. Using CPU" warning?</a> <a name="cuda-warning">How to fix "CUDA GPU is not available. Using CPU" warning?</a>
@@ -363,6 +380,18 @@ This will start Abogen in command-line mode and display detailed error messages.
</details> </details>
<details><summary><b>
<a name="use-uv-instead-of-pip">How to use "uv" instead of "pip"?</a>
</b></summary>
> Abogen needs "pip", because Kokoro uses pip to download voice models from HuggingFace Hub. If you want to use "uv" instead of "pip", you can use the following command to run Abogen:
>
> ```bash
> uvx --with pip abogen
> ```
</details>
## `Contributing` ## `Contributing`
I welcome contributions! If you have ideas for new features, improvements, or bug fixes, please fork the repository and submit a pull request. I welcome contributions! If you have ideas for new features, improvements, or bug fixes, please fork the repository and submit a pull request.
### For developers and contributors ### For developers and contributors
@@ -387,6 +416,9 @@ Feel free to explore the code and make any changes you like.
This project is available under the MIT License - see the [LICENSE](https://github.com/denizsafak/abogen/blob/main/LICENSE) file for details. This project is available under the MIT License - see the [LICENSE](https://github.com/denizsafak/abogen/blob/main/LICENSE) file for details.
[Kokoro](https://github.com/hexgrad/kokoro) is licensed under [Apache-2.0](https://github.com/hexgrad/kokoro/blob/main/LICENSE) which allows commercial use, modification, distribution, and private use. [Kokoro](https://github.com/hexgrad/kokoro) is licensed under [Apache-2.0](https://github.com/hexgrad/kokoro/blob/main/LICENSE) which allows commercial use, modification, distribution, and private use.
## `Star History`
[![Star History Chart](https://api.star-history.com/svg?repos=denizsafak/abogen&type=Date)](https://www.star-history.com/#denizsafak/abogen&Date)
> [!IMPORTANT] > [!IMPORTANT]
> Subtitle generation currently works only for English. This is because Kokoro provides timestamp tokens only for English text. If you want subtitles in other languages, please request this feature in the [Kokoro project](https://github.com/hexgrad/kokoro). For more technical details, see [this line](https://github.com/hexgrad/kokoro/blob/6d87f4ae7abc2d14dbc4b3ef2e5f19852e861ac2/kokoro/pipeline.py#L383) in the Kokoro's code. > Subtitle generation currently works only for English. This is because Kokoro provides timestamp tokens only for English text. If you want subtitles in other languages, please request this feature in the [Kokoro project](https://github.com/hexgrad/kokoro). For more technical details, see [this line](https://github.com/hexgrad/kokoro/blob/6d87f4ae7abc2d14dbc4b3ef2e5f19852e861ac2/kokoro/pipeline.py#L383) in the Kokoro's code.
+1 -1
View File
@@ -1 +1 @@
1.1.8 1.1.9
+10 -5
View File
@@ -231,20 +231,24 @@ class HandlerDialog(QDialog):
if not self.markdown_text: if not self.markdown_text:
return return
text = clean_text(self.markdown_text) # Generate TOC from the original (dedented) markdown BEFORE cleaning,
text = textwrap.dedent(text) # so header ids/anchors are preserved for reliable position detection.
original_text = textwrap.dedent(self.markdown_text)
md = markdown.Markdown(extensions=['toc', 'fenced_code']) md = markdown.Markdown(extensions=['toc', 'fenced_code'])
html = md.convert(text) html = md.convert(original_text)
self.markdown_toc = md.toc_tokens self.markdown_toc = md.toc_tokens
# Use cleaned text for stored content/length calculations
cleaned_full_text = clean_text(original_text)
soup = BeautifulSoup(html, 'html.parser') soup = BeautifulSoup(html, 'html.parser')
self.content_texts = {} self.content_texts = {}
self.content_lengths = {} self.content_lengths = {}
if not self.markdown_toc: if not self.markdown_toc:
chapter_id = "markdown_content" chapter_id = "markdown_content"
self.content_texts[chapter_id] = text self.content_texts[chapter_id] = cleaned_full_text
self.content_lengths[chapter_id] = calculate_text_length(text) self.content_lengths[chapter_id] = calculate_text_length(cleaned_full_text)
return return
all_headers = [] all_headers = []
@@ -279,6 +283,7 @@ class HandlerDialog(QDialog):
header_tag = section_soup.find(attrs={'id': header_id}) header_tag = section_soup.find(attrs={'id': header_id})
if header_tag: if header_tag:
header_tag.decompose() header_tag.decompose()
# Clean section text for storage/lengths
section_text = clean_text(section_soup.get_text()).strip() section_text = clean_text(section_soup.get_text()).strip()
chapter_id = header_id chapter_id = header_id
if section_text: if section_text:
+1 -17
View File
@@ -1189,23 +1189,7 @@ class ConversionThread(QThread):
if not tokens_with_timestamps: if not tokens_with_timestamps:
return return
# Always combine punctuation with preceding words for consistent handling across modes processed_tokens = tokens_with_timestamps # Use tokens directly
processed_tokens = []
i = 0
while i < len(tokens_with_timestamps):
token = tokens_with_timestamps[i].copy()
# Look ahead for punctuation
while i + 1 < len(tokens_with_timestamps) and re.match(
r"^[^\w\s]+$", tokens_with_timestamps[i + 1]["text"]
):
token["text"] += tokens_with_timestamps[i + 1]["text"]
token["end"] = tokens_with_timestamps[i + 1]["end"]
token["whitespace"] = tokens_with_timestamps[i + 1]["whitespace"]
i += 1
processed_tokens.append(token)
i += 1
# Use processed_tokens instead of tokens_with_timestamps for the rest of the method # Use processed_tokens instead of tokens_with_timestamps for the rest of the method
if self.subtitle_mode == "Sentence + Highlighting": if self.subtitle_mode == "Sentence + Highlighting":
+1 -1
View File
@@ -140,7 +140,7 @@ class QueueManager(QDialog):
instructions = QLabel( instructions = QLabel(
"<h2>How Queue Works?</h2>" "<h2>How Queue Works?</h2>"
"You can add text files (.txt) directly using the '<b>Add files</b>' button below. " "You can add text files (.txt) directly using the '<b>Add files</b>' button below. "
"To add PDF or EPUB files, use the input box in the main window and click the <b>'Add to Queue'</b> button. " "To add PDF, EPUB or markdown files, use the input box in the main window and click the <b>'Add to Queue'</b> button. "
"Each file in the queue keeps the configuration settings active when it was added. " "Each file in the queue keeps the configuration settings active when it was added. "
"Changing the main window configuration afterward <b>does not</b> affect files already in the queue. " "Changing the main window configuration afterward <b>does not</b> affect files already in the queue. "
"You can view each file's configuration by hovering over them." "You can view each file's configuration by hovering over them."