From 375a185aefef923c7aa44c37635336d4f4e70e7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deniz=20=C5=9Eafak?= Date: Thu, 8 May 2025 20:43:44 +0300 Subject: [PATCH] Added `.opus` support as output format for generated audio files. --- CHANGELOG.md | 1 + abogen/conversion.py | 66 +++++++++++++++++++++++++++++++++++++++----- abogen/gui.py | 1 + 3 files changed, 61 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0233c16..049d9ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # v1.0.7 (pre-release) - Ignore chapter markers and single newlines when calculating text length. +- Added `.opus` support as output format for generated audio files. - Added "Playing..." indicator for "Preview" button in the voice mixer. # v1.0.6 diff --git a/abogen/conversion.py b/abogen/conversion.py index 863a05a..61b09d0 100644 --- a/abogen/conversion.py +++ b/abogen/conversion.py @@ -511,12 +511,38 @@ class ConversionThread(QThread): chapter_out_path = os.path.join( chapters_out_dir, f"{chapter_filename}.{chapter_ext}" ) - sf.write( - chapter_out_path, - chapter_audio, - 24000, - format=chapter_format, - ) + if self.output_format == "opus": + static_ffmpeg.add_paths() + proc = subprocess.Popen( + [ + "ffmpeg", + "-y", + "-f", + "f32le", + "-ar", + "24000", + "-ac", + "1", + "-i", + "pipe:", + "-c:a", + "libopus", + "-b:a", + "24000", + chapter_out_path, + ], + stdin=subprocess.PIPE, + ) + proc.stdin.write(chapter_audio.astype("float32").tobytes()) + proc.stdin.close() + proc.wait() + else: + sf.write( + chapter_out_path, + chapter_audio, + 24000, + format=chapter_format, + ) # Generate .srt subtitle file for chapter if not Disabled if self.subtitle_mode != "Disabled" and chapter_subtitle_entries: @@ -571,7 +597,33 @@ class ConversionThread(QThread): out_path = os.path.splitext(out_path)[0] + ".wav" self.output_format = "wav" m4b_picked = True - sf.write(out_path, audio, 24000, format=self.output_format) + if self.output_format == "opus": + static_ffmpeg.add_paths() + proc = subprocess.Popen( + [ + "ffmpeg", + "-y", + "-f", + "f32le", + "-ar", + "24000", + "-ac", + "1", + "-i", + "pipe:", + "-c:a", + "libopus", + "-b:a", + "24000", + out_path, + ], + stdin=subprocess.PIPE, + ) + proc.stdin.write(audio.astype("float32").tobytes()) + proc.stdin.close() + proc.wait() + else: + sf.write(out_path, audio, 24000, format=self.output_format) if m4b_picked: out_path = self._generate_m4b_with_chapters(out_path, chapters_time) diff --git a/abogen/gui.py b/abogen/gui.py index 97e2a11..b7514af 100644 --- a/abogen/gui.py +++ b/abogen/gui.py @@ -695,6 +695,7 @@ class abogen(QWidget): ("wav", "wav"), ("flac", "flac"), ("mp3", "mp3"), + ("opus", "opus (best)"), ("m4b", "m4b (with chapters)"), ]: self.format_combo.addItem(label, key)