diff --git a/README.md b/README.md index 5b49965..03d0f59 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@ using Kokoro's high-quality speech synthesis. [Kokoro-82M](https://huggingface.co/hexgrad/Kokoro-82M) is a recently published text-to-speech model with just 82M params and very natural sounding output. It's released under Apache licence and it was trained on < 100 hours of audio. -It currently supports American and British English in a bunch of very good voices. +It currently supports American and British English in a bunch of very good voices. -**Future support for French, Korean, Japanese and Mandarin is planned.** +Future support for French, Korean, Japanese and Mandarin is planned. On a Google Colab's T4 GPU via Cuda, **it takes about 5 minutes to convert "Animal's Farm" by Orwell** (which is a bout 160,000 characters) to audiobook, at a rate of about 600 characters per second. @@ -23,9 +23,12 @@ On my M2 MacBook Pro, on CPU, it takes about 1 hour, at a rate of about 60 chara ## How to install and run If you have Python 3 on your computer, you can install it with pip. +You also need `espeak-ng` installed on your machine: ```bash pip install audiblez +sudo apt install espeak-ng # on Ubuntu/Debian +brew install espeak-ng # on Mac ``` Then, to convert an epub file into an audiobook, just run: diff --git a/audiblez.py b/audiblez.py index 4463cf6..3a2f7d4 100755 --- a/audiblez.py +++ b/audiblez.py @@ -38,14 +38,14 @@ def main(pipeline, file_path, voice, pick_manually, speed): meta_title = book.get_metadata('DC', 'title') title = meta_title[0][0] if meta_title else '' meta_creator = book.get_metadata('DC', 'creator') - creator = meta_creator[0][0] if meta_creator else '' + by_creator = 'by ' + meta_creator[0][0] if meta_creator else '' cover_maybe = [c for c in book.get_items() if c.get_type() == ebooklib.ITEM_COVER] cover_image = cover_maybe[0].get_content() if cover_maybe else b"" if cover_maybe: print(f'Found cover image {cover_maybe[0].file_name} in {cover_maybe[0].media_type} format') - intro = f'{title} by {creator}' + intro = f'{title} {by_creator}' print(intro) print('Found Chapters:', [c.get_name() for c in book.get_items() if c.get_type() == ebooklib.ITEM_DOCUMENT]) if pick_manually: @@ -95,7 +95,7 @@ def main(pipeline, file_path, voice, pick_manually, speed): print('Progress:', f'{progress}%\n') if has_ffmpeg: - create_index_file(title, creator, chapter_mp3_files) + create_index_file(title, by_creator, chapter_mp3_files) create_m4b(chapter_mp3_files, filename, cover_image) diff --git a/test/test_main.py b/test/test_main.py index 97b4ad0..74db2c6 100644 --- a/test/test_main.py +++ b/test/test_main.py @@ -1,3 +1,4 @@ +import os import unittest from pathlib import Path @@ -11,11 +12,6 @@ class MainTest(unittest.TestCase): pipeline = KPipeline(lang_code='a') main(pipeline, file_path=file_path, voice='af_sky', pick_manually=False, speed=1, **kwargs) - # def test_0_txt(self): - # Path('book.m4b').unlink(missing_ok=True) - # self.base(file_path='../txt/book.txt') - # self.assertTrue(Path('book.m4b').exists()) - def test_1_mini(self): Path('mini.m4b').unlink(missing_ok=True) self.base(file_path='../epub/mini.epub') @@ -26,12 +22,11 @@ class MainTest(unittest.TestCase): self.base(file_path='../epub/poe.epub') self.assertTrue(Path('poe.m4b').exists()) - # def test_3_gene(self): - # Path('gene.m4b').unlink(missing_ok=True) - # self.base(file_path='../epub/gene.epub') - # self.assertTrue(Path('gene.m4b').exists()) - def test_orwell(self): Path('orwell.m4b').unlink(missing_ok=True) + os.system('rm orwell_chapter_*.wav') self.base(file_path='../epub/orwell.epub') self.assertTrue(Path('orwell.m4b').exists()) + for i in range(8): + self.assertTrue(Path(f'orwell_chapter_{i}.wav').exists()) + self.assertTrue(Path(f'orwell_chapter_{i}.wav').stat().st_size > 300 * 1024, 'file should be larger than 300KB, surely failed')