This commit is contained in:
Claudio Santini 2025-01-23 21:44:26 +01:00
parent f62d20e5d2
commit 5182971aa9

View file

@ -38,7 +38,7 @@ def main(kokoro, file_path, lang, voice, pick_manually, speed, providers):
kokoro.sess.set_providers(providers) kokoro.sess.set_providers(providers)
print(f"Using ONNX providers: {', '.join(providers)}") print(f"Using ONNX providers: {', '.join(providers)}")
filename = Path(file_path).name filename = Path(file_path).name
with warnings.catch_warnings(): warnings.simplefilter("ignore")
book = epub.read_epub(file_path) book = epub.read_epub(file_path)
title = book.get_metadata('DC', 'title')[0][0] title = book.get_metadata('DC', 'title')[0][0]
creator = book.get_metadata('DC', 'creator')[0][0] creator = book.get_metadata('DC', 'creator')[0][0]
@ -55,7 +55,7 @@ def main(kokoro, file_path, lang, voice, pick_manually, speed, providers):
chapters = pick_chapters(book) chapters = pick_chapters(book)
else: else:
chapters = find_chapters(book) chapters = find_chapters(book)
print('Selected chapters:', [c.get_name() for c in chapters]) print('Automatically selected chapters:', [c.get_name() for c in chapters])
texts = extract_texts(chapters) texts = extract_texts(chapters)
has_ffmpeg = shutil.which('ffmpeg') is not None has_ffmpeg = shutil.which('ffmpeg') is not None
@ -73,23 +73,16 @@ def main(kokoro, file_path, lang, voice, pick_manually, speed, providers):
for i, text in enumerate(texts, start=1): for i, text in enumerate(texts, start=1):
if len(text.strip()) < 10: if len(text.strip()) < 10:
print(f'Skipping empty chapter {i}') print(f'Skipping empty chapter {i}')
chapter_mp3_files.remove(chapter_filename)
continue continue
chapter_filename = filename.replace('.epub', f'_chapter_{i}.wav') chapter_filename = filename.replace('.epub', f'_chapter_{i}.wav')
chapter_mp3_files.append(chapter_filename) chapter_mp3_files.append(chapter_filename)
if Path(chapter_filename).exists(): if Path(chapter_filename).exists():
print(f'File for chapter {i} already exists. Skipping') print(f'File for chapter {i} already exists. Skipping')
i += 1
continue continue
if len(text.strip()) < 10:
print(f'Skipping empty chapter {i}')
i += 1
chapter_mp3_files.remove(chapter_filename)
continue
print(f'Reading chapter {i} ({len(text):,} characters)...') print(f'Reading chapter {i} ({len(text):,} characters)...')
if i == 1: if i == 1:
text = intro + '.\n\n' + text text = intro + '.\n\n' + text
start_time = time.time() start_time = time.time()
samples, sample_rate = kokoro.create(text, voice=voice, speed=speed, lang=lang) samples, sample_rate = kokoro.create(text, voice=voice, speed=speed, lang=lang)
sf.write(f'{chapter_filename}', samples, sample_rate) sf.write(f'{chapter_filename}', samples, sample_rate)
@ -104,7 +97,7 @@ def main(kokoro, file_path, lang, voice, pick_manually, speed, providers):
print('Chapter written to', chapter_filename) print('Chapter written to', chapter_filename)
print(f'Chapter {i} read in {delta_seconds:.2f} seconds ({chars_per_sec:.0f} characters per second)') print(f'Chapter {i} read in {delta_seconds:.2f} seconds ({chars_per_sec:.0f} characters per second)')
progress = processed_chars * 100 // total_chars progress = processed_chars * 100 // total_chars
print('Progress:', f'{progress}%') print('Progress:', f'{progress}%\n')
if has_ffmpeg: if has_ffmpeg:
create_index_file(title, creator, chapter_mp3_files, durations) create_index_file(title, creator, chapter_mp3_files, durations)
@ -211,11 +204,13 @@ def create_m4b(chapter_files, filename, title, author, cover_image):
print(f'{final_filename} created. Enjoy your audiobook.') print(f'{final_filename} created. Enjoy your audiobook.')
print('Feel free to delete the intermediary .wav chapter files, the .m4b is all you need.') print('Feel free to delete the intermediary .wav chapter files, the .m4b is all you need.')
def probe_duration(file_name): def probe_duration(file_name):
args = ['ffprobe', '-i', file_name, '-show_entries', 'format=duration', '-v', 'quiet', '-of', 'default=noprint_wrappers=1:nokey=1'] args = ['ffprobe', '-i', file_name, '-show_entries', 'format=duration', '-v', 'quiet', '-of', 'default=noprint_wrappers=1:nokey=1']
proc = subprocess.run(args, capture_output=True, text=True, check=True) proc = subprocess.run(args, capture_output=True, text=True, check=True)
return float(proc.stdout.strip()) return float(proc.stdout.strip())
def create_index_file(title, creator, chapter_mp3_files, durations): def create_index_file(title, creator, chapter_mp3_files, durations):
with open("chapters.txt", "w") as f: with open("chapters.txt", "w") as f:
f.write(f";FFMETADATA1\ntitle={title}\nartist={creator}\n\n") f.write(f";FFMETADATA1\ntitle={title}\nartist={creator}\n\n")