From f1fa3404940e1422010b9be19f9b4996619e5e57 Mon Sep 17 00:00:00 2001 From: remsky Date: Sat, 5 Apr 2025 04:09:28 -0600 Subject: [PATCH 01/20] Update README.md --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d9b5a61..46b6f00 100644 --- a/README.md +++ b/README.md @@ -34,10 +34,12 @@ Pre built images are available to run, with arm/multi-arch support, and baked in Refer to the core/config.py file for a full list of variables which can be managed via the environment ```bash -# the `latest` tag can be used, though it may have some unexpected bonus features which impact stability. Named versions should be pinned for your regular usage. Feedback/testing is always welcome +# the `latest` tag can be used, though it may have some unexpected bonus features which impact stability. + Named versions should be pinned for your regular usage. + Feedback/testing is always welcome -docker run -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-cpu:v0.3.0 # CPU, or: -docker run --gpus all -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-gpu:v0.3.0 #NVIDIA GPU +docker run -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-cpu:latest # CPU, or: +docker run --gpus all -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-gpu:latest #NVIDIA GPU ``` From 83325b749da4b1bfb9c44ce088515be5d597a828 Mon Sep 17 00:00:00 2001 From: Rodrigo Iglesias <8595185+RigleGit@users.noreply.github.com> Date: Thu, 17 Apr 2025 16:07:15 +0200 Subject: [PATCH 02/20] Update Dockerfile to install Rust Rust is required to build sudachipy and pyopenjtalk-plus --- docker/cpu/Dockerfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docker/cpu/Dockerfile b/docker/cpu/Dockerfile index d770a6c..f528307 100644 --- a/docker/cpu/Dockerfile +++ b/docker/cpu/Dockerfile @@ -30,6 +30,10 @@ WORKDIR /app # Copy dependency files COPY --chown=appuser:appuser pyproject.toml ./pyproject.toml +# Install Rust (required to build sudachipy and pyopenjtalk-plus) +RUN curl https://sh.rustup.rs -sSf | sh -s -- -y +ENV PATH="/home/appuser/.cargo/bin:$PATH" + # Install dependencies RUN --mount=type=cache,target=/root/.cache/uv \ uv venv --python 3.10 && \ From 48e096b4416f7ed187d334392906344969894d4e Mon Sep 17 00:00:00 2001 From: Fireblade2534 Date: Thu, 1 May 2025 17:53:01 +0000 Subject: [PATCH 03/20] Massivly improved how number, time, and money normalization --- .../services/text_processing/normalizer.py | 132 ++++++++++++------ api/tests/test_normalizer.py | 97 ++++++++++++- dev/Test copy 2.py | 38 +++++ outputstream.wav | Bin 0 -> 148208 bytes 4 files changed, 218 insertions(+), 49 deletions(-) create mode 100644 dev/Test copy 2.py create mode 100644 outputstream.wav diff --git a/api/src/services/text_processing/normalizer.py b/api/src/services/text_processing/normalizer.py index e9f73c0..8876f0c 100644 --- a/api/src/services/text_processing/normalizer.py +++ b/api/src/services/text_processing/normalizer.py @@ -6,11 +6,13 @@ Converts them into a format suitable for text-to-speech processing. import re from functools import lru_cache +from typing import List, Optional, Union import inflect from numpy import number from text_to_num import text2num from torch import mul +import math from ...structures.schemas import NormalizationOptions @@ -132,6 +134,11 @@ VALID_UNITS = { "px": "pixel", # CSS units } +MONEY_UNITS = { + "$": ("dollar", "cent"), + "£": ("pound", "pence"), + "€": ("euro", "cent") +} # Pre-compiled regex patterns for performance EMAIL_PATTERN = re.compile( @@ -152,37 +159,22 @@ UNIT_PATTERN = re.compile( ) TIME_PATTERN = re.compile( - r"([0-9]{2} ?: ?[0-9]{2}( ?: ?[0-9]{2})?)( ?(pm|am)\b)?", re.IGNORECASE + r"([0-9]{1,2} ?: ?[0-9]{2}( ?: ?[0-9]{2})?)( ?(pm|am)\b)?", + re.IGNORECASE +) + +MONEY_PATTERN = re.compile( + r"(-?)([" + ''.join(MONEY_UNITS.keys()) + r"])(\d+(?:\.\d+)?)((?: hundred| thousand| (?:[bm]|tr|quadr)illion|k|m|b|t)*)\b", + re.IGNORECASE +) + +NUMBER_PATTERN = re.compile( + r"(-?)(\d+(?:\.\d+)?)((?: hundred| thousand| (?:[bm]|tr|quadr)illion|k|m|b)*)\b", + re.IGNORECASE ) INFLECT_ENGINE = inflect.engine() - -def split_num(num: re.Match[str]) -> str: - """Handle number splitting for various formats""" - num = num.group() - if "." in num: - return num - elif ":" in num: - h, m = [int(n) for n in num.split(":")] - if m == 0: - return f"{h} o'clock" - elif m < 10: - return f"{h} oh {m}" - return f"{h} {m}" - year = int(num[:4]) - if year < 1100 or year % 1000 < 10: - return num - left, right = num[:2], int(num[2:4]) - s = "s" if num.endswith("s") else "" - if 100 <= year % 1000 <= 999: - if right == 0: - return f"{left} hundred{s}" - elif right < 10: - return f"{left} oh {right}{s}" - return f"{left} {right}{s}" - - def handle_units(u: re.Match[str]) -> str: """Converts units to their full form""" unit_string = u.group(6).strip() @@ -207,15 +199,48 @@ def conditional_int(number: float, threshold: float = 0.00001): return int(round(number)) return number +def translate_multiplier(multiplier: str) -> str: + """Translate multiplier abrevations to words""" + + multiplier_translation = {"k": "thousand", "m": "million", "b": "billion", "t": "trillion"} + if multiplier.lower() in multiplier_translation: + return multiplier_translation[multiplier.lower()] + return multiplier.strip() + +def split_four_digit(number: float): + part1 = str(conditional_int(number))[:2] + part2 = str(conditional_int(number))[2:] + return f"{INFLECT_ENGINE.number_to_words(part1)} {INFLECT_ENGINE.number_to_words(part2)}" + +def handle_numbers(n: re.Match[str]) -> str: + number = n.group(2) + + try: + number = float(number) + except: + return n.group() + + if n.group(1) == "-": + number *= -1 + + multiplier = translate_multiplier(n.group(3)) + + number = conditional_int(number) + if multiplier != "": + multiplier = f" {multiplier}" + else: + if number % 1 == 0 and len(str(number)) == 4 and number > 1500 and number % 1000 > 9: + return split_four_digit(number) + + return f"{INFLECT_ENGINE.number_to_words(number)}{multiplier}" def handle_money(m: re.Match[str]) -> str: """Convert money expressions to spoken form""" - bill = "dollar" if m.group(2) == "$" else "pound" - coin = "cent" if m.group(2) == "$" else "pence" - number = m.group(3) + bill, coin = MONEY_UNITS[m.group(2)] - multiplier = m.group(4) + number = m.group(3) + try: number = float(number) except: @@ -224,12 +249,17 @@ def handle_money(m: re.Match[str]) -> str: if m.group(1) == "-": number *= -1 + multiplier = translate_multiplier(m.group(4)) + + if multiplier != "": + multiplier = f" {multiplier}" + if number % 1 == 0 or multiplier != "": text_number = f"{INFLECT_ENGINE.number_to_words(conditional_int(number))}{multiplier} {INFLECT_ENGINE.plural(bill, count=number)}" else: sub_number = int(str(number).split(".")[-1].ljust(2, "0")) - text_number = f"{INFLECT_ENGINE.number_to_words(int(round(number)))} {INFLECT_ENGINE.plural(bill, count=number)} and {INFLECT_ENGINE.number_to_words(sub_number)} {INFLECT_ENGINE.plural(coin, count=sub_number)}" + text_number = f"{INFLECT_ENGINE.number_to_words(int(math.floor(number)))} {INFLECT_ENGINE.plural(bill, count=number)} and {INFLECT_ENGINE.number_to_words(sub_number)} {INFLECT_ENGINE.plural(coin, count=sub_number)}" return text_number @@ -320,15 +350,31 @@ def handle_phone_number(p: re.Match[str]) -> str: def handle_time(t: re.Match[str]) -> str: t = t.groups() - numbers = " ".join( - [INFLECT_ENGINE.number_to_words(X.strip()) for X in t[0].split(":")] - ) + time_parts = t[0].split(":") + + numbers = [] + numbers.append(INFLECT_ENGINE.number_to_words(time_parts[0].strip())) + + minute_number = INFLECT_ENGINE.number_to_words(time_parts[1].strip()) + if int(time_parts[1]) < 10: + if int(time_parts[1]) != 0: + numbers.append(f"oh {minute_number}") + else: + numbers.append(minute_number) half = "" - if t[2] is not None: - half = t[2].strip() + if len(time_parts) > 2: + seconds_number = INFLECT_ENGINE.number_to_words(time_parts[2].strip()) + second_word = INFLECT_ENGINE.plural('second',int(time_parts[2].strip())) + numbers.append(f"and {seconds_number} {second_word}") + else: + if t[2] is not None: + half = " " + t[2].strip() + else: + if int(time_parts[1]) == 0: + numbers.append("o'clock") - return numbers + half + return " ".join(numbers) + half def normalize_text(text: str, normalization_options: NormalizationOptions) -> str: @@ -366,7 +412,7 @@ def normalize_text(text: str, normalization_options: NormalizationOptions) -> st for a, b in zip("、。!,:;?–", ",.!,:;?-"): text = text.replace(a, b + " ") - # Handle simple time in the format of HH:MM:SS + # Handle simple time in the format of HH:MM:SS (am/pm) text = TIME_PATTERN.sub( handle_time, text, @@ -390,14 +436,14 @@ def normalize_text(text: str, normalization_options: NormalizationOptions) -> st # Handle numbers and money text = re.sub(r"(?<=\d),(?=\d)", "", text) - text = re.sub( - r"(?i)(-?)([$£])(\d+(?:\.\d+)?)((?: hundred| thousand| (?:[bm]|tr|quadr)illion)*)\b", + text = MONEY_PATTERN.sub( handle_money, text, ) - text = re.sub( - r"\d*\.\d+|\b\d{4}s?\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%0A=8} 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

`8*Kp~$j~l`r)Z?#^ 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ℑ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 a|E%|a9|C`3`+py1f9CiT0{`0}@P7bdLBWUs literal 0 HcmV?d00001 From f89b76d5d6a125e818c4e9f1ebb81b573785e3d3 Mon Sep 17 00:00:00 2001 From: Fireblade2534 Date: Thu, 1 May 2025 18:02:35 +0000 Subject: [PATCH 04/20] Added more tests --- api/tests/test_normalizer.py | 10 ++++++++++ outputstream.wav | Bin 148208 -> 0 bytes 2 files changed, 10 insertions(+) delete mode 100644 outputstream.wav diff --git a/api/tests/test_normalizer.py b/api/tests/test_normalizer.py index 4a589b4..93b3f76 100644 --- a/api/tests/test_normalizer.py +++ b/api/tests/test_normalizer.py @@ -206,6 +206,11 @@ def test_time(): == "It is currently three o'clock" ) + assert ( + normalize_text("12:00 am is midnight", normalization_options=NormalizationOptions()) + == "twelve am is midnight" + ) + def test_number(): """Test number normalization""" @@ -244,6 +249,11 @@ def test_number(): == "He made minus fifty sales today." ) + assert ( + normalize_text("56.789 to the power of 1.35 million", normalization_options=NormalizationOptions()) + == "fifty-six point seven eight nine to the power of one point three five million" + ) + def test_non_url_text(): """Test that non-URL text is unaffected""" assert ( diff --git a/outputstream.wav b/outputstream.wav deleted file mode 100644 index 41b2d30eed2435da1266a8493d81d2309f72271c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 148208 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%0A=8} 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

`8*Kp~$j~l`r)Z?#^ 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ℑ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 a|E%|a9|C`3`+py1f9CiT0{`0}@P7bdLBWUs From c80d4feb69550339767dcf3142294793d8deda40 Mon Sep 17 00:00:00 2001 From: Fireblade2534 Date: Thu, 1 May 2025 18:16:36 +0000 Subject: [PATCH 05/20] Fixed formatting --- .../services/text_processing/normalizer.py | 47 ++++++----- api/tests/test_normalizer.py | 79 ++++++++++++++----- dev/Test copy 2.py | 2 +- 3 files changed, 90 insertions(+), 38 deletions(-) diff --git a/api/src/services/text_processing/normalizer.py b/api/src/services/text_processing/normalizer.py index 8876f0c..280a26e 100644 --- a/api/src/services/text_processing/normalizer.py +++ b/api/src/services/text_processing/normalizer.py @@ -4,6 +4,7 @@ Handles various text formats including URLs, emails, numbers, money, and special Converts them into a format suitable for text-to-speech processing. """ +import math import re from functools import lru_cache from typing import List, Optional, Union @@ -12,7 +13,6 @@ import inflect from numpy import number from text_to_num import text2num from torch import mul -import math from ...structures.schemas import NormalizationOptions @@ -134,11 +134,7 @@ VALID_UNITS = { "px": "pixel", # CSS units } -MONEY_UNITS = { - "$": ("dollar", "cent"), - "£": ("pound", "pence"), - "€": ("euro", "cent") -} +MONEY_UNITS = {"$": ("dollar", "cent"), "£": ("pound", "pence"), "€": ("euro", "cent")} # Pre-compiled regex patterns for performance EMAIL_PATTERN = re.compile( @@ -159,22 +155,24 @@ UNIT_PATTERN = re.compile( ) TIME_PATTERN = re.compile( - r"([0-9]{1,2} ?: ?[0-9]{2}( ?: ?[0-9]{2})?)( ?(pm|am)\b)?", - re.IGNORECASE + r"([0-9]{1,2} ?: ?[0-9]{2}( ?: ?[0-9]{2})?)( ?(pm|am)\b)?", re.IGNORECASE ) MONEY_PATTERN = re.compile( - r"(-?)([" + ''.join(MONEY_UNITS.keys()) + r"])(\d+(?:\.\d+)?)((?: hundred| thousand| (?:[bm]|tr|quadr)illion|k|m|b|t)*)\b", - re.IGNORECASE + r"(-?)([" + + "".join(MONEY_UNITS.keys()) + + r"])(\d+(?:\.\d+)?)((?: hundred| thousand| (?:[bm]|tr|quadr)illion|k|m|b|t)*)\b", + re.IGNORECASE, ) NUMBER_PATTERN = re.compile( r"(-?)(\d+(?:\.\d+)?)((?: hundred| thousand| (?:[bm]|tr|quadr)illion|k|m|b)*)\b", - re.IGNORECASE + re.IGNORECASE, ) INFLECT_ENGINE = inflect.engine() + def handle_units(u: re.Match[str]) -> str: """Converts units to their full form""" unit_string = u.group(6).strip() @@ -199,19 +197,27 @@ def conditional_int(number: float, threshold: float = 0.00001): return int(round(number)) return number + def translate_multiplier(multiplier: str) -> str: """Translate multiplier abrevations to words""" - multiplier_translation = {"k": "thousand", "m": "million", "b": "billion", "t": "trillion"} + multiplier_translation = { + "k": "thousand", + "m": "million", + "b": "billion", + "t": "trillion", + } if multiplier.lower() in multiplier_translation: return multiplier_translation[multiplier.lower()] return multiplier.strip() + def split_four_digit(number: float): part1 = str(conditional_int(number))[:2] part2 = str(conditional_int(number))[2:] return f"{INFLECT_ENGINE.number_to_words(part1)} {INFLECT_ENGINE.number_to_words(part2)}" + def handle_numbers(n: re.Match[str]) -> str: number = n.group(2) @@ -229,18 +235,24 @@ def handle_numbers(n: re.Match[str]) -> str: if multiplier != "": multiplier = f" {multiplier}" else: - if number % 1 == 0 and len(str(number)) == 4 and number > 1500 and number % 1000 > 9: + if ( + number % 1 == 0 + and len(str(number)) == 4 + and number > 1500 + and number % 1000 > 9 + ): return split_four_digit(number) return f"{INFLECT_ENGINE.number_to_words(number)}{multiplier}" + def handle_money(m: re.Match[str]) -> str: """Convert money expressions to spoken form""" bill, coin = MONEY_UNITS[m.group(2)] number = m.group(3) - + try: number = float(number) except: @@ -365,7 +377,7 @@ def handle_time(t: re.Match[str]) -> str: half = "" if len(time_parts) > 2: seconds_number = INFLECT_ENGINE.number_to_words(time_parts[2].strip()) - second_word = INFLECT_ENGINE.plural('second',int(time_parts[2].strip())) + second_word = INFLECT_ENGINE.plural("second", int(time_parts[2].strip())) numbers.append(f"and {seconds_number} {second_word}") else: if t[2] is not None: @@ -441,10 +453,7 @@ def normalize_text(text: str, normalization_options: NormalizationOptions) -> st text, ) - text = NUMBER_PATTERN.sub( - handle_numbers, - text - ) + text = NUMBER_PATTERN.sub(handle_numbers, text) text = re.sub(r"\d*\.\d+", handle_decimal, text) diff --git a/api/tests/test_normalizer.py b/api/tests/test_normalizer.py index 93b3f76..3db0801 100644 --- a/api/tests/test_normalizer.py +++ b/api/tests/test_normalizer.py @@ -149,8 +149,8 @@ def test_money(): assert ( normalize_text( - "He went gambling and lost about $25.05k.", - normalization_options=NormalizationOptions() + "He went gambling and lost about $25.05k.", + normalization_options=NormalizationOptions(), ) == "He went gambling and lost about twenty-five point zero five thousand dollars." ) @@ -169,91 +169,134 @@ def test_money(): ) assert ( - normalize_text("The plant cost $200,000.8.", normalization_options=NormalizationOptions()) + normalize_text( + "The plant cost $200,000.8.", normalization_options=NormalizationOptions() + ) == "The plant cost two hundred thousand dollars and eighty cents." ) assert ( - normalize_text("€30.2 is in euros", normalization_options=NormalizationOptions()) + normalize_text( + "€30.2 is in euros", normalization_options=NormalizationOptions() + ) == "thirty euros and twenty cents is in euros" ) + def test_time(): """Test time normalization""" assert ( - normalize_text("Your flight leaves at 10:35 pm", normalization_options=NormalizationOptions()) + normalize_text( + "Your flight leaves at 10:35 pm", + normalization_options=NormalizationOptions(), + ) == "Your flight leaves at ten thirty-five pm" ) assert ( - normalize_text("He departed for london around 5:03 am.", normalization_options=NormalizationOptions()) + normalize_text( + "He departed for london around 5:03 am.", + normalization_options=NormalizationOptions(), + ) == "He departed for london around five oh three am." ) assert ( - normalize_text("Only the 13:42 and 15:12 slots are available.", normalization_options=NormalizationOptions()) + normalize_text( + "Only the 13:42 and 15:12 slots are available.", + normalization_options=NormalizationOptions(), + ) == "Only the thirteen forty-two and fifteen twelve slots are available." ) assert ( - normalize_text("It is currently 1:00 pm", normalization_options=NormalizationOptions()) + normalize_text( + "It is currently 1:00 pm", normalization_options=NormalizationOptions() + ) == "It is currently one pm" ) assert ( - normalize_text("It is currently 3:00", normalization_options=NormalizationOptions()) + normalize_text( + "It is currently 3:00", normalization_options=NormalizationOptions() + ) == "It is currently three o'clock" ) assert ( - normalize_text("12:00 am is midnight", normalization_options=NormalizationOptions()) + normalize_text( + "12:00 am is midnight", normalization_options=NormalizationOptions() + ) == "twelve am is midnight" ) + def test_number(): """Test number normalization""" assert ( - normalize_text("I bought 1035 cans of soda", normalization_options=NormalizationOptions()) + normalize_text( + "I bought 1035 cans of soda", normalization_options=NormalizationOptions() + ) == "I bought one thousand and thirty-five cans of soda" ) assert ( - normalize_text("The bus has a maximum capacity of 62 people", normalization_options=NormalizationOptions()) + normalize_text( + "The bus has a maximum capacity of 62 people", + normalization_options=NormalizationOptions(), + ) == "The bus has a maximum capacity of sixty-two people" ) assert ( - normalize_text("There are 1300 products left in stock", normalization_options=NormalizationOptions()) + normalize_text( + "There are 1300 products left in stock", + normalization_options=NormalizationOptions(), + ) == "There are one thousand, three hundred products left in stock" ) assert ( - normalize_text("The population is 7,890,000 people.", normalization_options=NormalizationOptions()) + normalize_text( + "The population is 7,890,000 people.", + normalization_options=NormalizationOptions(), + ) == "The population is seven million, eight hundred and ninety thousand people." ) assert ( - normalize_text("He looked around but only found 1.6k of the 10k bricks", normalization_options=NormalizationOptions()) + normalize_text( + "He looked around but only found 1.6k of the 10k bricks", + normalization_options=NormalizationOptions(), + ) == "He looked around but only found one point six thousand of the ten thousand bricks" ) assert ( - normalize_text("The book has 342 pages.", normalization_options=NormalizationOptions()) + normalize_text( + "The book has 342 pages.", normalization_options=NormalizationOptions() + ) == "The book has three hundred and forty-two pages." ) assert ( - normalize_text("He made -50 sales today.", normalization_options=NormalizationOptions()) + normalize_text( + "He made -50 sales today.", normalization_options=NormalizationOptions() + ) == "He made minus fifty sales today." ) assert ( - normalize_text("56.789 to the power of 1.35 million", normalization_options=NormalizationOptions()) + normalize_text( + "56.789 to the power of 1.35 million", + normalization_options=NormalizationOptions(), + ) == "fifty-six point seven eight nine to the power of one point three five million" ) + def test_non_url_text(): """Test that non-URL text is unaffected""" assert ( diff --git a/dev/Test copy 2.py b/dev/Test copy 2.py index eecbea5..52634ec 100644 --- a/dev/Test copy 2.py +++ b/dev/Test copy 2.py @@ -35,4 +35,4 @@ for chunk in response.iter_lines(decode_unicode=True): f.write(chunk_audio) # Print word level timestamps - print(chunk_json["timestamps"]) \ No newline at end of file + print(chunk_json["timestamps"]) From acee9792253bcfb0a2365564921c99ce45d1e655 Mon Sep 17 00:00:00 2001 From: Fireblade2534 Date: Fri, 2 May 2025 13:34:08 +0000 Subject: [PATCH 06/20] Fixed phenomes --- api/src/routers/development.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/src/routers/development.py b/api/src/routers/development.py index e749119..605481b 100644 --- a/api/src/routers/development.py +++ b/api/src/routers/development.py @@ -104,7 +104,7 @@ async def generate_from_phonemes( if chunk_audio is not None: # Normalize audio before writing - normalized_audio = await normalizer.normalize(chunk_audio) + normalized_audio = normalizer.normalize(chunk_audio) # Write chunk and yield bytes chunk_bytes = writer.write_chunk(normalized_audio) if chunk_bytes: @@ -114,6 +114,7 @@ async def generate_from_phonemes( final_bytes = writer.write_chunk(finalize=True) if final_bytes: yield final_bytes + writer.close() else: raise ValueError("Failed to generate audio data") From 1ac9924c3eff77c188525d023e558bb7f7f19245 Mon Sep 17 00:00:00 2001 From: Fireblade2534 Date: Fri, 9 May 2025 13:04:53 +0000 Subject: [PATCH 07/20] Added some better safty checks to captioned speech --- api/src/routers/development.py | 13 ++++++++----- dev/Test Phon.py | 23 +++++++++++++++++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 dev/Test Phon.py diff --git a/api/src/routers/development.py b/api/src/routers/development.py index e749119..bde0843 100644 --- a/api/src/routers/development.py +++ b/api/src/routers/development.py @@ -223,10 +223,13 @@ async def create_captioned_speech( ).decode("utf-8") # Add any chunks that may be in the acumulator into the return word_timestamps - chunk_data.word_timestamps = ( - timestamp_acumulator + chunk_data.word_timestamps - ) - timestamp_acumulator = [] + if chunk_data.word_timestamps is not None: + chunk_data.word_timestamps = ( + timestamp_acumulator + chunk_data.word_timestamps + ) + timestamp_acumulator = [] + else: + chunk_data.word_timestamps = [] yield CaptionedSpeechResponse( audio=base64_chunk, @@ -271,7 +274,7 @@ async def create_captioned_speech( ) # Add any chunks that may be in the acumulator into the return word_timestamps - if chunk_data.word_timestamps != None: + if chunk_data.word_timestamps is not None: chunk_data.word_timestamps = ( timestamp_acumulator + chunk_data.word_timestamps ) diff --git a/dev/Test Phon.py b/dev/Test Phon.py new file mode 100644 index 0000000..d3ba783 --- /dev/null +++ b/dev/Test Phon.py @@ -0,0 +1,23 @@ +import base64 +import json + +import pydub +import requests + +def generate_audio_from_phonemes(phonemes: str, voice: str = "af_bella"): + """Generate audio from phonemes""" + response = requests.post( + "http://localhost:8880/dev/generate_from_phonemes", + json={"phonemes": phonemes, "voice": voice}, + headers={"Accept": "audio/wav"} + ) + if response.status_code != 200: + print(f"Error: {response.text}") + return None + return response.content + + + + +with open(f"outputnostreammoney.wav", "wb") as f: + f.write(generate_audio_from_phonemes(r"mɪsəki ɪz ɐn ɪkspˌɛɹəmˈɛntᵊl ʤˈitəpˈi ˈɛnʤən dəzˈInd tə pˈWəɹ fjˈuʧəɹ vˈɜɹʒənz ʌv kəkˈɔɹO mˈɑdᵊlz.")) \ No newline at end of file From b0f46276ebe0168a3c02c0fca68fd9cc8f4ecbd9 Mon Sep 17 00:00:00 2001 From: Mike Bailey Date: Sun, 11 May 2025 01:00:41 +1000 Subject: [PATCH 08/20] Update paths.py Use root_dir instead of /app This was breaking things for me when I started the app from a script that was not in the root_dir --- api/src/core/paths.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/core/paths.py b/api/src/core/paths.py index 0e60528..771b70c 100644 --- a/api/src/core/paths.py +++ b/api/src/core/paths.py @@ -300,7 +300,7 @@ async def get_web_file_path(filename: str) -> str: ) # Construct web directory path relative to project root - web_dir = os.path.join("/app", settings.web_player_path) + web_dir = os.path.join(root_dir, settings.web_player_path) # Search in web directory search_paths = [web_dir] From 75963c4aebea9c570b3ee015521869f4ea10a3e0 Mon Sep 17 00:00:00 2001 From: JCallicoat Date: Thu, 22 May 2025 06:49:37 -0500 Subject: [PATCH 09/20] Add a volume multiplier setting Allow configuring output volume via multiplier applied to np array of audio chunk. Defaults to 1.0 which is no-op. Fixes #110 --- api/src/core/config.py | 1 + api/src/inference/model_manager.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/api/src/core/config.py b/api/src/core/config.py index 1d4657c..3bc825c 100644 --- a/api/src/core/config.py +++ b/api/src/core/config.py @@ -31,6 +31,7 @@ class Settings(BaseSettings): # Audio Settings sample_rate: int = 24000 + volume_multiplier: float = 1.0 # Text Processing Settings target_min_tokens: int = 175 # Target minimum tokens per chunk target_max_tokens: int = 250 # Target maximum tokens per chunk diff --git a/api/src/inference/model_manager.py b/api/src/inference/model_manager.py index 9cef95f..0b4cd81 100644 --- a/api/src/inference/model_manager.py +++ b/api/src/inference/model_manager.py @@ -141,6 +141,8 @@ Model files not found! You need to download the Kokoro V1 model: try: async for chunk in self._backend.generate(*args, **kwargs): + if settings.volume_multiplier != 1.0: + chunk.audio *= settings.volume_multiplier yield chunk except Exception as e: raise RuntimeError(f"Generation failed: {e}") From ce22f60344c5a77a9d61b865b7081a8c4b589cb0 Mon Sep 17 00:00:00 2001 From: Fireblade2534 <77405729+fireblade2534@users.noreply.github.com> Date: Sat, 24 May 2025 21:31:38 -0400 Subject: [PATCH 10/20] Fix readme claiming that Korean is supported --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 46b6f00..5e9da1d 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ [![Tested at Model Commit](https://img.shields.io/badge/last--tested--model--commit-1.0::9901c2b-blue)](https://huggingface.co/hexgrad/Kokoro-82M/commit/9901c2b79161b6e898b7ea857ae5298f47b8b0d6) Dockerized FastAPI wrapper for [Kokoro-82M](https://huggingface.co/hexgrad/Kokoro-82M) text-to-speech model -- Multi-language support (English, Japanese, Korean, Chinese, _Vietnamese soon_) +- Multi-language support (English, Japanese, Chinese, _Vietnamese soon_) - OpenAI-compatible Speech endpoint, NVIDIA GPU accelerated or CPU inference with PyTorch - ONNX support coming soon, see v0.1.5 and earlier for legacy ONNX support in the interim - Debug endpoints for monitoring system stats, integrated web UI on localhost:8880/web From 9c279f2b5eac3d85e793576c959621f13eaacaa2 Mon Sep 17 00:00:00 2001 From: jiaohuix <1152937237@qq.com> Date: Mon, 26 May 2025 15:30:03 +0800 Subject: [PATCH 11/20] feat(text): add Chinese punctuation-based sentence splitting for better TTS --- .../services/text_processing/normalizer.py | 2 +- .../text_processing/text_processor.py | 64 ++++++++++++------- 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/api/src/services/text_processing/normalizer.py b/api/src/services/text_processing/normalizer.py index 280a26e..5e5d6b6 100644 --- a/api/src/services/text_processing/normalizer.py +++ b/api/src/services/text_processing/normalizer.py @@ -11,7 +11,7 @@ from typing import List, Optional, Union import inflect from numpy import number -from text_to_num import text2num +# from text_to_num import text2num from torch import mul from ...structures.schemas import NormalizationOptions diff --git a/api/src/services/text_processing/text_processor.py b/api/src/services/text_processing/text_processor.py index 584affe..77fd525 100644 --- a/api/src/services/text_processing/text_processor.py +++ b/api/src/services/text_processing/text_processor.py @@ -88,32 +88,48 @@ def process_text(text: str, language: str = "a") -> List[int]: def get_sentence_info( - text: str, custom_phenomes_list: Dict[str, str] + text: str, custom_phenomes_list: Dict[str, str], lang_code: str = "a" ) -> List[Tuple[str, List[int], int]]: - """Process all sentences and return info.""" - sentences = re.split(r"([.!?;:])(?=\s|$)", text) + """Process all sentences and return info, 支持中文分句""" + # 判断是否为中文 + is_chinese = lang_code.startswith("zh") or re.search(r"[\u4e00-\u9fff]", text) + if is_chinese: + # 按中文标点断句 + sentences = re.split(r"([,。!?;])", text) + # 合并标点 + merged = [] + for i in range(0, len(sentences)-1, 2): + merged.append(sentences[i] + sentences[i+1]) + if len(sentences) % 2 == 1: + merged.append(sentences[-1]) + sentences = merged + else: + sentences = re.split(r"([.!?;:])(?=\s|$)", text) phoneme_length, min_value = len(custom_phenomes_list), 0 - results = [] - for i in range(0, len(sentences), 2): - sentence = sentences[i].strip() - for replaced in range(min_value, phoneme_length): - current_id = f"" - if current_id in sentence: - sentence = sentence.replace( - current_id, custom_phenomes_list.pop(current_id) - ) - min_value += 1 - - punct = sentences[i + 1] if i + 1 < len(sentences) else "" - - if not sentence: - continue - - full = sentence + punct - tokens = process_text_chunk(full) - results.append((full, tokens, len(tokens))) - + if is_chinese: + for sentence in sentences: + sentence = sentence.strip() + if not sentence: + continue + tokens = process_text_chunk(sentence) + results.append((sentence, tokens, len(tokens))) + else: + for i in range(0, len(sentences), 2): + sentence = sentences[i].strip() + for replaced in range(min_value, phoneme_length): + current_id = f"" + if current_id in sentence: + sentence = sentence.replace( + current_id, custom_phenomes_list.pop(current_id) + ) + min_value += 1 + punct = sentences[i + 1] if i + 1 < len(sentences) else "" + if not sentence: + continue + full = sentence + punct + tokens = process_text_chunk(full) + results.append((full, tokens, len(tokens))) return results @@ -150,7 +166,7 @@ async def smart_split( ) # Process all sentences - sentences = get_sentence_info(text, custom_phoneme_list) + sentences = get_sentence_info(text, custom_phoneme_list, lang_code=lang_code) current_chunk = [] current_tokens = [] From b89da1ff280d1d32bc70b8df01ff3c738e7889ba Mon Sep 17 00:00:00 2001 From: Fireblade2534 Date: Wed, 28 May 2025 14:53:00 +0000 Subject: [PATCH 12/20] Make the code cleaner and add tests --- .../services/text_processing/phonemizer.py | 2 +- .../text_processing/text_processor.py | 51 ++++++--------- api/tests/test_text_processor.py | 62 +++++++++++++++++++ dev/Test money.py | 6 +- 4 files changed, 83 insertions(+), 38 deletions(-) diff --git a/api/src/services/text_processing/phonemizer.py b/api/src/services/text_processing/phonemizer.py index 5a50d64..c010005 100644 --- a/api/src/services/text_processing/phonemizer.py +++ b/api/src/services/text_processing/phonemizer.py @@ -75,7 +75,7 @@ def create_phonemizer(language: str = "a") -> PhonemizerBackend: Phonemizer backend instance """ # Map language codes to espeak language codes - lang_map = {"a": "en-us", "b": "en-gb"} + lang_map = {"a": "en-us", "b": "en-gb", "z": "z"} if language not in lang_map: raise ValueError(f"Unsupported language code: {language}") diff --git a/api/src/services/text_processing/text_processor.py b/api/src/services/text_processing/text_processor.py index 77fd525..0dbb348 100644 --- a/api/src/services/text_processing/text_processor.py +++ b/api/src/services/text_processing/text_processor.py @@ -92,44 +92,30 @@ def get_sentence_info( ) -> List[Tuple[str, List[int], int]]: """Process all sentences and return info, 支持中文分句""" # 判断是否为中文 - is_chinese = lang_code.startswith("zh") or re.search(r"[\u4e00-\u9fff]", text) + is_chinese = lang_code.startswith("z") or re.search(r"[\u4e00-\u9fff]", text) if is_chinese: # 按中文标点断句 - sentences = re.split(r"([,。!?;])", text) - # 合并标点 - merged = [] - for i in range(0, len(sentences)-1, 2): - merged.append(sentences[i] + sentences[i+1]) - if len(sentences) % 2 == 1: - merged.append(sentences[-1]) - sentences = merged + sentences = re.split(r"([,。!?;])+", text) else: sentences = re.split(r"([.!?;:])(?=\s|$)", text) phoneme_length, min_value = len(custom_phenomes_list), 0 + results = [] - if is_chinese: - for sentence in sentences: - sentence = sentence.strip() - if not sentence: - continue - tokens = process_text_chunk(sentence) - results.append((sentence, tokens, len(tokens))) - else: - for i in range(0, len(sentences), 2): - sentence = sentences[i].strip() - for replaced in range(min_value, phoneme_length): - current_id = f"" - if current_id in sentence: - sentence = sentence.replace( - current_id, custom_phenomes_list.pop(current_id) - ) - min_value += 1 - punct = sentences[i + 1] if i + 1 < len(sentences) else "" - if not sentence: - continue - full = sentence + punct - tokens = process_text_chunk(full) - results.append((full, tokens, len(tokens))) + for i in range(0, len(sentences), 2): + sentence = sentences[i].strip() + for replaced in range(min_value, phoneme_length): + current_id = f"" + if current_id in sentence: + sentence = sentence.replace( + current_id, custom_phenomes_list.pop(current_id) + ) + min_value += 1 + punct = sentences[i + 1] if i + 1 < len(sentences) else "" + if not sentence: + continue + full = sentence + punct + tokens = process_text_chunk(full) + results.append((full, tokens, len(tokens))) return results @@ -154,7 +140,6 @@ async def smart_split( # Normalize text if settings.advanced_text_normalization and normalization_options.normalize: - print(lang_code) if lang_code in ["a", "b", "en-us", "en-gb"]: text = CUSTOM_PHONEMES.sub( lambda s: handle_custom_phonemes(s, custom_phoneme_list), text diff --git a/api/tests/test_text_processor.py b/api/tests/test_text_processor.py index bfcbcfe..6ff8282 100644 --- a/api/tests/test_text_processor.py +++ b/api/tests/test_text_processor.py @@ -103,3 +103,65 @@ async def test_smart_split_with_punctuation(): # Verify punctuation is preserved assert all(any(p in chunk for p in "!?;:.") for chunk in chunks) + +def test_process_text_chunk_chinese_phonemes(): + """Test processing with Chinese pinyin phonemes.""" + pinyin = "nǐ hǎo lì" # Example pinyin sequence with tones + tokens = process_text_chunk(pinyin, skip_phonemize=True, language="z") + assert isinstance(tokens, list) + assert len(tokens) > 0 + + +def test_get_sentence_info_chinese(): + """Test Chinese sentence splitting and info extraction.""" + text = "这是一个句子。这是第二个句子!第三个问题?" + results = get_sentence_info(text, {}, lang_code="z") + + assert len(results) == 3 + for sentence, tokens, count in results: + assert isinstance(sentence, str) + assert isinstance(tokens, list) + assert isinstance(count, int) + assert count == len(tokens) + assert count > 0 + +@pytest.mark.asyncio +async def test_smart_split_chinese_short(): + """Test Chinese smart splitting with short text.""" + text = "这是一句话。" + chunks = [] + async for chunk_text, chunk_tokens in smart_split(text, lang_code="z"): + chunks.append((chunk_text, chunk_tokens)) + + assert len(chunks) == 1 + assert isinstance(chunks[0][0], str) + assert isinstance(chunks[0][1], list) + + +@pytest.mark.asyncio +async def test_smart_split_chinese_long(): + """Test Chinese smart splitting with longer text.""" + text = "。".join([f"测试句子 {i}" for i in range(20)]) + + chunks = [] + async for chunk_text, chunk_tokens in smart_split(text, lang_code="z"): + chunks.append((chunk_text, chunk_tokens)) + + assert len(chunks) > 1 + for chunk_text, chunk_tokens in chunks: + assert isinstance(chunk_text, str) + assert isinstance(chunk_tokens, list) + assert len(chunk_tokens) > 0 + + +@pytest.mark.asyncio +async def test_smart_split_chinese_punctuation(): + """Test Chinese smart splitting with punctuation preservation.""" + text = "第一句!第二问?第三句;第四句:第五句。" + + chunks = [] + async for chunk_text, _ in smart_split(text, lang_code="z"): + chunks.append(chunk_text) + + # Verify Chinese punctuation is preserved + assert all(any(p in chunk for p in "!?;:。") for chunk in chunks) \ No newline at end of file diff --git a/dev/Test money.py b/dev/Test money.py index 47e2a9c..57d1fa6 100644 --- a/dev/Test money.py +++ b/dev/Test money.py @@ -3,9 +3,7 @@ import json import requests -text = """the administration has offered up a platter of repression for more than a year and is still slated to lose $400 million. - -Columbia is the largest private landowner in New York City and boasts an endowment of $14.8 billion;""" +text = """奶酪芝士很浓郁!臭豆腐芝士有争议?陈年奶酪价格昂贵。""" Type = "wav" @@ -15,7 +13,7 @@ response = requests.post( json={ "model": "kokoro", "input": text, - "voice": "af_heart+af_sky", + "voice": "zf_xiaobei", "speed": 1.0, "response_format": Type, "stream": False, From ab8ab7d7494b47b11d8dfc17b72acf77e63bdd9e Mon Sep 17 00:00:00 2001 From: Lukin Date: Fri, 30 May 2025 22:52:58 +0800 Subject: [PATCH 13/20] Refactor audio processing and text normalization: Update audio normalization to use absolute amplitude threshold, enhance streaming audio writer with MP3 container options, and improve text normalization by stripping spaces and handling special characters to prevent audio artifacts. --- api/src/services/audio.py | 4 ++-- api/src/services/streaming_audio_writer.py | 24 +++++++++++++++---- .../services/text_processing/normalizer.py | 24 ++++++++++++++++++- .../services/text_processing/phonemizer.py | 17 +++++++++++-- .../text_processing/text_processor.py | 24 ++++++++++++++----- .../services/text_processing/vocabulary.py | 2 ++ 6 files changed, 80 insertions(+), 15 deletions(-) diff --git a/api/src/services/audio.py b/api/src/services/audio.py index 5d1d3ff..6ae6d79 100644 --- a/api/src/services/audio.py +++ b/api/src/services/audio.py @@ -80,12 +80,12 @@ class AudioNormalizer: non_silent_index_start, non_silent_index_end = None, None for X in range(0, len(audio_data)): - if audio_data[X] > amplitude_threshold: + if abs(audio_data[X]) > amplitude_threshold: non_silent_index_start = X break for X in range(len(audio_data) - 1, -1, -1): - if audio_data[X] > amplitude_threshold: + if abs(audio_data[X]) > amplitude_threshold: non_silent_index_end = X break diff --git a/api/src/services/streaming_audio_writer.py b/api/src/services/streaming_audio_writer.py index e6ec2d6..85740aa 100644 --- a/api/src/services/streaming_audio_writer.py +++ b/api/src/services/streaming_audio_writer.py @@ -32,19 +32,29 @@ class StreamingAudioWriter: if self.format in ["wav", "flac", "mp3", "pcm", "aac", "opus"]: if self.format != "pcm": self.output_buffer = BytesIO() + container_options = {} + # Try disabling Xing VBR header for MP3 to fix iOS timeline reading issues + if self.format == 'mp3': + # Disable Xing VBR header + container_options = {'write_xing': '0'} + logger.debug("Disabling Xing VBR header for MP3 encoding.") + self.container = av.open( self.output_buffer, mode="w", format=self.format if self.format != "aac" else "adts", + options=container_options # Pass options here ) self.stream = self.container.add_stream( codec_map[self.format], - sample_rate=self.sample_rate, + rate=self.sample_rate, # Correct parameter name is 'rate' layout="mono" if self.channels == 1 else "stereo", ) - self.stream.bit_rate = 128000 + # Set bit_rate only for codecs where it's applicable and useful + if self.format in ['mp3', 'aac', 'opus']: + self.stream.bit_rate = 128000 # Example bitrate, can be configured else: - raise ValueError(f"Unsupported format: {format}") + raise ValueError(f"Unsupported format: {self.format}") # Use self.format here def close(self): if hasattr(self, "container"): @@ -65,12 +75,18 @@ class StreamingAudioWriter: if finalize: if self.format != "pcm": + # Flush stream encoder packets = self.stream.encode(None) for packet in packets: self.container.mux(packet) + # Closing the container handles writing the trailer and finalizing the file. + # No explicit flush method is available or needed here. + logger.debug("Muxed final packets.") + + # Get the final bytes from the buffer *before* closing it data = self.output_buffer.getvalue() - self.close() + self.close() # Close container and buffer return data if audio_data is None or len(audio_data) == 0: diff --git a/api/src/services/text_processing/normalizer.py b/api/src/services/text_processing/normalizer.py index 5e5d6b6..2163cbc 100644 --- a/api/src/services/text_processing/normalizer.py +++ b/api/src/services/text_processing/normalizer.py @@ -391,6 +391,7 @@ def handle_time(t: re.Match[str]) -> str: def normalize_text(text: str, normalization_options: NormalizationOptions) -> str: """Normalize text for TTS processing""" + # Handle email addresses first if enabled if normalization_options.email_normalization: text = EMAIL_PATTERN.sub(handle_email, text) @@ -415,7 +416,7 @@ def normalize_text(text: str, normalization_options: NormalizationOptions) -> st text, ) - # Replace quotes and brackets + # Replace quotes and brackets (additional cleanup) text = text.replace(chr(8216), "'").replace(chr(8217), "'") text = text.replace("«", chr(8220)).replace("»", chr(8221)) text = text.replace(chr(8220), '"').replace(chr(8221), '"') @@ -435,6 +436,27 @@ def normalize_text(text: str, normalization_options: NormalizationOptions) -> st text = re.sub(r" +", " ", text) text = re.sub(r"(?<=\n) +(?=\n)", "", text) + # Handle special characters that might cause audio artifacts first + # Replace newlines with spaces (or pauses if needed) + text = text.replace('\n', ' ') + text = text.replace('\r', ' ') + + # Handle other problematic symbols + text = text.replace('~', '') # Remove tilde + text = text.replace('@', ' at ') # At symbol + text = text.replace('#', ' number ') # Hash/pound + text = text.replace('$', ' dollar ') # Dollar sign (if not handled by money pattern) + text = text.replace('%', ' percent ') # Percent sign + text = text.replace('^', '') # Caret + text = text.replace('&', ' and ') # Ampersand + text = text.replace('*', '') # Asterisk + text = text.replace('_', ' ') # Underscore to space + text = text.replace('|', ' ') # Pipe to space + text = text.replace('\\', ' ') # Backslash to space + text = text.replace('/', ' slash ') # Forward slash to space (unless in URLs) + text = text.replace('=', ' equals ') # Equals sign + text = text.replace('+', ' plus ') # Plus sign + # Handle titles and abbreviations text = re.sub(r"\bD[Rr]\.(?= [A-Z])", "Doctor", text) text = re.sub(r"\b(?:Mr\.|MR\.(?= [A-Z]))", "Mister", text) diff --git a/api/src/services/text_processing/phonemizer.py b/api/src/services/text_processing/phonemizer.py index c010005..ae49cd9 100644 --- a/api/src/services/text_processing/phonemizer.py +++ b/api/src/services/text_processing/phonemizer.py @@ -4,6 +4,7 @@ from abc import ABC, abstractmethod import phonemizer from .normalizer import normalize_text +from ...structures.schemas import NormalizationOptions phonemizers = {} @@ -95,8 +96,20 @@ def phonemize(text: str, language: str = "a", normalize: bool = True) -> str: Phonemized text """ global phonemizers + + # Strip input text first to remove problematic leading/trailing spaces + text = text.strip() + if normalize: - text = normalize_text(text) + # Create default normalization options and normalize text + normalization_options = NormalizationOptions() + text = normalize_text(text, normalization_options) + # Strip again after normalization + text = text.strip() + if language not in phonemizers: phonemizers[language] = create_phonemizer(language) - return phonemizers[language].phonemize(text) + + result = phonemizers[language].phonemize(text) + # Final strip to ensure no leading/trailing spaces in phonemes + return result.strip() diff --git a/api/src/services/text_processing/text_processor.py b/api/src/services/text_processing/text_processor.py index 0dbb348..3d90325 100644 --- a/api/src/services/text_processing/text_processor.py +++ b/api/src/services/text_processing/text_processor.py @@ -30,6 +30,12 @@ def process_text_chunk( List of token IDs """ start_time = time.time() + + # Strip input text to remove any leading/trailing spaces that could cause artifacts + text = text.strip() + + if not text: + return [] if skip_phonemize: # Input is already phonemes, just tokenize @@ -43,6 +49,8 @@ def process_text_chunk( t0 = time.time() phonemes = phonemize(text, language, normalize=False) # Already normalized + # Strip phonemes result to ensure no extra spaces + phonemes = phonemes.strip() t1 = time.time() t0 = time.time() @@ -114,6 +122,10 @@ def get_sentence_info( if not sentence: continue full = sentence + punct + # Strip the full sentence to remove any leading/trailing spaces before processing + full = full.strip() + if not full: # Skip if empty after stripping + continue tokens = process_text_chunk(full) results.append((full, tokens, len(tokens))) return results @@ -162,7 +174,7 @@ async def smart_split( if count > max_tokens: # Yield current chunk if any if current_chunk: - chunk_text = " ".join(current_chunk) + chunk_text = " ".join(current_chunk).strip() # Strip after joining chunk_count += 1 logger.debug( f"Yielding chunk {chunk_count}: '{chunk_text[:50]}{'...' if len(text) > 50 else ''}' ({current_count} tokens)" @@ -201,7 +213,7 @@ async def smart_split( else: # Yield clause chunk if we have one if clause_chunk: - chunk_text = " ".join(clause_chunk) + chunk_text = " ".join(clause_chunk).strip() # Strip after joining chunk_count += 1 logger.debug( f"Yielding clause chunk {chunk_count}: '{chunk_text[:50]}{'...' if len(text) > 50 else ''}' ({clause_count} tokens)" @@ -213,7 +225,7 @@ async def smart_split( # Don't forget last clause chunk if clause_chunk: - chunk_text = " ".join(clause_chunk) + chunk_text = " ".join(clause_chunk).strip() # Strip after joining chunk_count += 1 logger.debug( f"Yielding final clause chunk {chunk_count}: '{chunk_text[:50]}{'...' if len(text) > 50 else ''}' ({clause_count} tokens)" @@ -227,7 +239,7 @@ async def smart_split( ): # If we have a good sized chunk and adding next sentence exceeds target, # yield current chunk and start new one - chunk_text = " ".join(current_chunk) + chunk_text = " ".join(current_chunk).strip() # Strip after joining chunk_count += 1 logger.info( f"Yielding chunk {chunk_count}: '{chunk_text[:50]}{'...' if len(text) > 50 else ''}' ({current_count} tokens)" @@ -252,7 +264,7 @@ async def smart_split( else: # Yield current chunk and start new one if current_chunk: - chunk_text = " ".join(current_chunk) + chunk_text = " ".join(current_chunk).strip() # Strip after joining chunk_count += 1 logger.info( f"Yielding chunk {chunk_count}: '{chunk_text[:50]}{'...' if len(text) > 50 else ''}' ({current_count} tokens)" @@ -264,7 +276,7 @@ async def smart_split( # Don't forget the last chunk if current_chunk: - chunk_text = " ".join(current_chunk) + chunk_text = " ".join(current_chunk).strip() # Strip after joining chunk_count += 1 logger.info( f"Yielding final chunk {chunk_count}: '{chunk_text[:50]}{'...' if len(text) > 50 else ''}' ({current_count} tokens)" diff --git a/api/src/services/text_processing/vocabulary.py b/api/src/services/text_processing/vocabulary.py index 7a12892..d6d7863 100644 --- a/api/src/services/text_processing/vocabulary.py +++ b/api/src/services/text_processing/vocabulary.py @@ -23,6 +23,8 @@ def tokenize(phonemes: str) -> list[int]: Returns: List of token IDs """ + # Strip phonemes to remove leading/trailing spaces that could cause artifacts + phonemes = phonemes.strip() return [i for i in map(VOCAB.get, phonemes) if i is not None] From 84d2a4d806ecb3bf49021a36fe27b7eaa792c8c0 Mon Sep 17 00:00:00 2001 From: Lukin Date: Fri, 30 May 2025 23:06:41 +0800 Subject: [PATCH 14/20] Enhance TTS text processing: Implement pause tag handling in smart_split, allowing for better audio chunk generation with pauses. Update related tests to validate new functionality and ensure compatibility with existing features. --- .../text_processing/text_processor.py | 293 ++++++++++-------- api/src/services/tts_service.py | 112 ++++--- api/tests/test_text_processor.py | 44 ++- 3 files changed, 282 insertions(+), 167 deletions(-) diff --git a/api/src/services/text_processing/text_processor.py b/api/src/services/text_processing/text_processor.py index 3d90325..c5a442d 100644 --- a/api/src/services/text_processing/text_processor.py +++ b/api/src/services/text_processing/text_processor.py @@ -2,7 +2,7 @@ import re import time -from typing import AsyncGenerator, Dict, List, Tuple +from typing import AsyncGenerator, Dict, List, Tuple, Optional from loguru import logger @@ -13,7 +13,11 @@ from .phonemizer import phonemize from .vocabulary import tokenize # Pre-compiled regex patterns for performance -CUSTOM_PHONEMES = re.compile(r"(\[([^\]]|\n)*?\])(\(\/([^\/)]|\n)*?\/\))") +# Updated regex to be more strict and avoid matching isolated brackets +# Only matches complete patterns like [word](/ipa/) and prevents catastrophic backtracking +CUSTOM_PHONEMES = re.compile(r"(\[[^\[\]]*?\])(\(\/[^\/\(\)]*?\/\))") +# Pattern to find pause tags like [pause:0.5s] +PAUSE_TAG_PATTERN = re.compile(r"\[pause:(\d+(?:\.\d+)?)s\]", re.IGNORECASE) def process_text_chunk( @@ -142,148 +146,189 @@ async def smart_split( max_tokens: int = settings.absolute_max_tokens, lang_code: str = "a", normalization_options: NormalizationOptions = NormalizationOptions(), -) -> AsyncGenerator[Tuple[str, List[int]], None]: - """Build optimal chunks targeting 300-400 tokens, never exceeding max_tokens.""" +) -> AsyncGenerator[Tuple[str, List[int], Optional[float]], None]: + """Build optimal chunks targeting 300-400 tokens, never exceeding max_tokens. + + Yields: + Tuple of (text_chunk, tokens, pause_duration_s). + If pause_duration_s is not None, it's a pause chunk with empty text/tokens. + Otherwise, it's a text chunk containing the original text. + """ start_time = time.time() chunk_count = 0 logger.info(f"Starting smart split for {len(text)} chars") - custom_phoneme_list = {} + # --- Step 1: Split by Pause Tags FIRST --- + # This operates on the raw input text + parts = PAUSE_TAG_PATTERN.split(text) + logger.debug(f"Split raw text into {len(parts)} parts by pause tags.") - # Normalize text - if settings.advanced_text_normalization and normalization_options.normalize: - if lang_code in ["a", "b", "en-us", "en-gb"]: - text = CUSTOM_PHONEMES.sub( - lambda s: handle_custom_phonemes(s, custom_phoneme_list), text - ) - text = normalize_text(text, normalization_options) - else: - logger.info( - "Skipping text normalization as it is only supported for english" - ) + part_idx = 0 + while part_idx < len(parts): + text_part_raw = parts[part_idx] # This part is raw text + part_idx += 1 - # Process all sentences - sentences = get_sentence_info(text, custom_phoneme_list, lang_code=lang_code) + # --- Process Text Part --- + if text_part_raw and text_part_raw.strip(): # Only process if the part is not empty string + # Strip leading and trailing spaces to prevent pause tag splitting artifacts + text_part_raw = text_part_raw.strip() - current_chunk = [] - current_tokens = [] - current_count = 0 + # Apply the original smart_split logic to this text part + custom_phoneme_list = {} - for sentence, tokens, count in sentences: - # Handle sentences that exceed max tokens - if count > max_tokens: - # Yield current chunk if any - if current_chunk: - chunk_text = " ".join(current_chunk).strip() # Strip after joining - chunk_count += 1 - logger.debug( - f"Yielding chunk {chunk_count}: '{chunk_text[:50]}{'...' if len(text) > 50 else ''}' ({current_count} tokens)" - ) - yield chunk_text, current_tokens - current_chunk = [] - current_tokens = [] - current_count = 0 - - # Split long sentence on commas - clauses = re.split(r"([,])", sentence) - clause_chunk = [] - clause_tokens = [] - clause_count = 0 - - for j in range(0, len(clauses), 2): - clause = clauses[j].strip() - comma = clauses[j + 1] if j + 1 < len(clauses) else "" - - if not clause: - continue - - full_clause = clause + comma - - tokens = process_text_chunk(full_clause) - count = len(tokens) - - # If adding clause keeps us under max and not optimal yet - if ( - clause_count + count <= max_tokens - and clause_count + count <= settings.target_max_tokens - ): - clause_chunk.append(full_clause) - clause_tokens.extend(tokens) - clause_count += count + # Normalize text (original logic) + processed_text = text_part_raw + if settings.advanced_text_normalization and normalization_options.normalize: + if lang_code in ["a", "b", "en-us", "en-gb"]: + processed_text = CUSTOM_PHONEMES.sub( + lambda s: handle_custom_phonemes(s, custom_phoneme_list), processed_text + ) + processed_text = normalize_text(processed_text, normalization_options) else: - # Yield clause chunk if we have one - if clause_chunk: - chunk_text = " ".join(clause_chunk).strip() # Strip after joining + logger.info( + "Skipping text normalization as it is only supported for english" + ) + + # Process all sentences (original logic) + sentences = get_sentence_info(processed_text, custom_phoneme_list, lang_code=lang_code) + + current_chunk = [] + current_tokens = [] + current_count = 0 + + for sentence, tokens, count in sentences: + # Handle sentences that exceed max tokens (original logic) + if count > max_tokens: + # Yield current chunk if any + if current_chunk: + chunk_text = " ".join(current_chunk).strip() chunk_count += 1 logger.debug( - f"Yielding clause chunk {chunk_count}: '{chunk_text[:50]}{'...' if len(text) > 50 else ''}' ({clause_count} tokens)" + f"Yielding chunk {chunk_count}: '{chunk_text[:50]}{'...' if len(processed_text) > 50 else ''}' ({current_count} tokens)" ) - yield chunk_text, clause_tokens - clause_chunk = [full_clause] - clause_tokens = tokens - clause_count = count + yield chunk_text, current_tokens, None + current_chunk = [] + current_tokens = [] + current_count = 0 - # Don't forget last clause chunk - if clause_chunk: - chunk_text = " ".join(clause_chunk).strip() # Strip after joining - chunk_count += 1 - logger.debug( - f"Yielding final clause chunk {chunk_count}: '{chunk_text[:50]}{'...' if len(text) > 50 else ''}' ({clause_count} tokens)" - ) - yield chunk_text, clause_tokens + # Split long sentence on commas (original logic) + clauses = re.split(r"([,])", sentence) + clause_chunk = [] + clause_tokens = [] + clause_count = 0 - # Regular sentence handling - elif ( - current_count >= settings.target_min_tokens - and current_count + count > settings.target_max_tokens - ): - # If we have a good sized chunk and adding next sentence exceeds target, - # yield current chunk and start new one - chunk_text = " ".join(current_chunk).strip() # Strip after joining - chunk_count += 1 - logger.info( - f"Yielding chunk {chunk_count}: '{chunk_text[:50]}{'...' if len(text) > 50 else ''}' ({current_count} tokens)" - ) - yield chunk_text, current_tokens - current_chunk = [sentence] - current_tokens = tokens - current_count = count - elif current_count + count <= settings.target_max_tokens: - # Keep building chunk while under target max - current_chunk.append(sentence) - current_tokens.extend(tokens) - current_count += count - elif ( - current_count + count <= max_tokens - and current_count < settings.target_min_tokens - ): - # Only exceed target max if we haven't reached minimum size yet - current_chunk.append(sentence) - current_tokens.extend(tokens) - current_count += count - else: - # Yield current chunk and start new one + for j in range(0, len(clauses), 2): + clause = clauses[j].strip() + comma = clauses[j + 1] if j + 1 < len(clauses) else "" + + if not clause: + continue + + full_clause = clause + comma + + tokens = process_text_chunk(full_clause) + count = len(tokens) + + # If adding clause keeps us under max and not optimal yet + if ( + clause_count + count <= max_tokens + and clause_count + count <= settings.target_max_tokens + ): + clause_chunk.append(full_clause) + clause_tokens.extend(tokens) + clause_count += count + else: + # Yield clause chunk if we have one + if clause_chunk: + chunk_text = " ".join(clause_chunk).strip() + chunk_count += 1 + logger.debug( + f"Yielding clause chunk {chunk_count}: '{chunk_text[:50]}{'...' if len(processed_text) > 50 else ''}' ({clause_count} tokens)" + ) + yield chunk_text, clause_tokens, None + clause_chunk = [full_clause] + clause_tokens = tokens + clause_count = count + + # Don't forget last clause chunk + if clause_chunk: + chunk_text = " ".join(clause_chunk).strip() + chunk_count += 1 + logger.debug( + f"Yielding final clause chunk {chunk_count}: '{chunk_text[:50]}{'...' if len(processed_text) > 50 else ''}' ({clause_count} tokens)" + ) + yield chunk_text, clause_tokens, None + + # Regular sentence handling (original logic) + elif ( + current_count >= settings.target_min_tokens + and current_count + count > settings.target_max_tokens + ): + # If we have a good sized chunk and adding next sentence exceeds target, + # yield current chunk and start new one + chunk_text = " ".join(current_chunk).strip() + chunk_count += 1 + logger.info( + f"Yielding chunk {chunk_count}: '{chunk_text[:50]}{'...' if len(processed_text) > 50 else ''}' ({current_count} tokens)" + ) + yield chunk_text, current_tokens, None + current_chunk = [sentence] + current_tokens = tokens + current_count = count + elif current_count + count <= settings.target_max_tokens: + # Keep building chunk while under target max + current_chunk.append(sentence) + current_tokens.extend(tokens) + current_count += count + elif ( + current_count + count <= max_tokens + and current_count < settings.target_min_tokens + ): + # Only exceed target max if we haven't reached minimum size yet + current_chunk.append(sentence) + current_tokens.extend(tokens) + current_count += count + else: + # Yield current chunk and start new one + if current_chunk: + chunk_text = " ".join(current_chunk).strip() + chunk_count += 1 + logger.info( + f"Yielding chunk {chunk_count}: '{chunk_text[:50]}{'...' if len(processed_text) > 50 else ''}' ({current_count} tokens)" + ) + yield chunk_text, current_tokens, None + current_chunk = [sentence] + current_tokens = tokens + current_count = count + + # Don't forget the last chunk for this text part if current_chunk: - chunk_text = " ".join(current_chunk).strip() # Strip after joining + chunk_text = " ".join(current_chunk).strip() chunk_count += 1 logger.info( - f"Yielding chunk {chunk_count}: '{chunk_text[:50]}{'...' if len(text) > 50 else ''}' ({current_count} tokens)" + f"Yielding final chunk {chunk_count} for part: '{chunk_text[:50]}{'...' if len(processed_text) > 50 else ''}' ({current_count} tokens)" ) - yield chunk_text, current_tokens - current_chunk = [sentence] - current_tokens = tokens - current_count = count + yield chunk_text, current_tokens, None - # Don't forget the last chunk - if current_chunk: - chunk_text = " ".join(current_chunk).strip() # Strip after joining - chunk_count += 1 - logger.info( - f"Yielding final chunk {chunk_count}: '{chunk_text[:50]}{'...' if len(text) > 50 else ''}' ({current_count} tokens)" - ) - yield chunk_text, current_tokens + # --- Handle Pause Part --- + # Check if the next part is a pause duration string + if part_idx < len(parts): + duration_str = parts[part_idx] + # Check if it looks like a valid number string captured by the regex group + if re.fullmatch(r"\d+(?:\.\d+)?", duration_str): + part_idx += 1 # Consume the duration string as it's been processed + try: + duration = float(duration_str) + if duration > 0: + chunk_count += 1 + logger.info(f"Yielding pause chunk {chunk_count}: {duration}s") + yield "", [], duration # Yield pause chunk + except (ValueError, TypeError): + # This case should be rare if re.fullmatch passed, but handle anyway + logger.warning(f"Could not parse valid-looking pause duration: {duration_str}") + # --- End of parts loop --- total_time = time.time() - start_time logger.info( - f"Split completed in {total_time * 1000:.2f}ms, produced {chunk_count} chunks" + f"Split completed in {total_time * 1000:.2f}ms, produced {chunk_count} chunks (including pauses)" ) diff --git a/api/src/services/tts_service.py b/api/src/services/tts_service.py index 0a69b85..399600e 100644 --- a/api/src/services/tts_service.py +++ b/api/src/services/tts_service.py @@ -280,48 +280,88 @@ class TTSService: f"Using lang_code '{pipeline_lang_code}' for voice '{voice_name}' in audio stream" ) - # Process text in chunks with smart splitting - async for chunk_text, tokens in smart_split( + # Process text in chunks with smart splitting, handling pause tags + async for chunk_text, tokens, pause_duration_s in smart_split( text, lang_code=pipeline_lang_code, normalization_options=normalization_options, ): - try: - # Process audio for chunk - async for chunk_data in self._process_chunk( - chunk_text, # Pass text for Kokoro V1 - tokens, # Pass tokens for legacy backends - voice_name, # Pass voice name - voice_path, # Pass voice path - speed, - writer, - output_format, - is_first=(chunk_index == 0), - is_last=False, # We'll update the last chunk later - normalizer=stream_normalizer, - lang_code=pipeline_lang_code, # Pass lang_code - return_timestamps=return_timestamps, - ): - if chunk_data.word_timestamps is not None: - for timestamp in chunk_data.word_timestamps: - timestamp.start_time += current_offset - timestamp.end_time += current_offset + if pause_duration_s is not None and pause_duration_s > 0: + # --- Handle Pause Chunk --- + try: + logger.debug(f"Generating {pause_duration_s}s silence chunk") + silence_samples = int(pause_duration_s * 24000) # 24kHz sample rate + # Create proper silence as int16 zeros to avoid normalization artifacts + silence_audio = np.zeros(silence_samples, dtype=np.int16) + pause_chunk = AudioChunk(audio=silence_audio, word_timestamps=[]) # Empty timestamps for silence - current_offset += len(chunk_data.audio) / 24000 - - if chunk_data.output is not None: - yield chunk_data - - else: - logger.warning( - f"No audio generated for chunk: '{chunk_text[:100]}...'" + # Format and yield the silence chunk + if output_format: + formatted_pause_chunk = await AudioService.convert_audio( + pause_chunk, output_format, writer, speed=speed, chunk_text="", + is_last_chunk=False, trim_audio=False, normalizer=stream_normalizer, ) - chunk_index += 1 - except Exception as e: - logger.error( - f"Failed to process audio for chunk: '{chunk_text[:100]}...'. Error: {str(e)}" - ) - continue + if formatted_pause_chunk.output: + yield formatted_pause_chunk + else: # Raw audio mode + # For raw audio mode, silence is already in the correct format (int16) + # Skip normalization to avoid any potential artifacts + if len(pause_chunk.audio) > 0: + yield pause_chunk + + # Update offset based on silence duration + current_offset += pause_duration_s + chunk_index += 1 # Count pause as a yielded chunk + + except Exception as e: + logger.error(f"Failed to process pause chunk: {str(e)}") + continue + + elif tokens or chunk_text.strip(): # Process if there are tokens OR non-whitespace text + # --- Handle Text Chunk --- + try: + # Process audio for chunk + async for chunk_data in self._process_chunk( + chunk_text, # Pass text for Kokoro V1 + tokens, # Pass tokens for legacy backends + voice_name, # Pass voice name + voice_path, # Pass voice path + speed, + writer, + output_format, + is_first=(chunk_index == 0), + is_last=False, # We'll update the last chunk later + normalizer=stream_normalizer, + lang_code=pipeline_lang_code, # Pass lang_code + return_timestamps=return_timestamps, + ): + if chunk_data.word_timestamps is not None: + for timestamp in chunk_data.word_timestamps: + timestamp.start_time += current_offset + timestamp.end_time += current_offset + + # Update offset based on the actual duration of the generated audio chunk + chunk_duration = 0 + if chunk_data.audio is not None and len(chunk_data.audio) > 0: + chunk_duration = len(chunk_data.audio) / 24000 + current_offset += chunk_duration + + # Yield the processed chunk (either formatted or raw) + if chunk_data.output is not None: + yield chunk_data + elif chunk_data.audio is not None and len(chunk_data.audio) > 0: + yield chunk_data + else: + logger.warning( + f"No audio generated for chunk: '{chunk_text[:100]}...'" + ) + + chunk_index += 1 # Increment chunk index after processing text + except Exception as e: + logger.error( + f"Failed to process audio for chunk: '{chunk_text[:100]}...'. Error: {str(e)}" + ) + continue # Only finalize if we successfully processed at least one chunk if chunk_index > 0: diff --git a/api/tests/test_text_processor.py b/api/tests/test_text_processor.py index 6ff8282..95c0259 100644 --- a/api/tests/test_text_processor.py +++ b/api/tests/test_text_processor.py @@ -67,7 +67,7 @@ async def test_smart_split_short_text(): """Test smart splitting with text under max tokens.""" text = "This is a short test sentence." chunks = [] - async for chunk_text, chunk_tokens in smart_split(text): + async for chunk_text, chunk_tokens, _ in smart_split(text): chunks.append((chunk_text, chunk_tokens)) assert len(chunks) == 1 @@ -82,7 +82,7 @@ async def test_smart_split_long_text(): text = ". ".join(["This is test sentence number " + str(i) for i in range(20)]) chunks = [] - async for chunk_text, chunk_tokens in smart_split(text): + async for chunk_text, chunk_tokens, _ in smart_split(text): chunks.append((chunk_text, chunk_tokens)) assert len(chunks) > 1 @@ -98,12 +98,13 @@ async def test_smart_split_with_punctuation(): text = "First sentence! Second sentence? Third sentence; Fourth sentence: Fifth sentence." chunks = [] - async for chunk_text, chunk_tokens in smart_split(text): + async for chunk_text, chunk_tokens, _ in smart_split(text): chunks.append(chunk_text) # Verify punctuation is preserved assert all(any(p in chunk for p in "!?;:.") for chunk in chunks) + def test_process_text_chunk_chinese_phonemes(): """Test processing with Chinese pinyin phonemes.""" pinyin = "nǐ hǎo lì" # Example pinyin sequence with tones @@ -125,12 +126,13 @@ def test_get_sentence_info_chinese(): assert count == len(tokens) assert count > 0 + @pytest.mark.asyncio async def test_smart_split_chinese_short(): """Test Chinese smart splitting with short text.""" text = "这是一句话。" chunks = [] - async for chunk_text, chunk_tokens in smart_split(text, lang_code="z"): + async for chunk_text, chunk_tokens, _ in smart_split(text, lang_code="z"): chunks.append((chunk_text, chunk_tokens)) assert len(chunks) == 1 @@ -144,7 +146,7 @@ async def test_smart_split_chinese_long(): text = "。".join([f"测试句子 {i}" for i in range(20)]) chunks = [] - async for chunk_text, chunk_tokens in smart_split(text, lang_code="z"): + async for chunk_text, chunk_tokens, _ in smart_split(text, lang_code="z"): chunks.append((chunk_text, chunk_tokens)) assert len(chunks) > 1 @@ -160,8 +162,36 @@ async def test_smart_split_chinese_punctuation(): text = "第一句!第二问?第三句;第四句:第五句。" chunks = [] - async for chunk_text, _ in smart_split(text, lang_code="z"): + async for chunk_text, _, _ in smart_split(text, lang_code="z"): chunks.append(chunk_text) # Verify Chinese punctuation is preserved - assert all(any(p in chunk for p in "!?;:。") for chunk in chunks) \ No newline at end of file + assert all(any(p in chunk for p in "!?;:。") for chunk in chunks) + + +@pytest.mark.asyncio +async def test_smart_split_with_pause(): + """Test smart splitting with pause tags.""" + text = "Hello world [pause:2.5s] How are you?" + + chunks = [] + async for chunk_text, chunk_tokens, pause_duration in smart_split(text): + chunks.append((chunk_text, chunk_tokens, pause_duration)) + + # Should have 3 chunks: text, pause, text + assert len(chunks) == 3 + + # First chunk: text + assert chunks[0][2] is None # No pause + assert "Hello world" in chunks[0][0] + assert len(chunks[0][1]) > 0 + + # Second chunk: pause + assert chunks[1][2] == 2.5 # 2.5 second pause + assert chunks[1][0] == "" # Empty text + assert len(chunks[1][1]) == 0 # No tokens + + # Third chunk: text + assert chunks[2][2] is None # No pause + assert "How are you?" in chunks[2][0] + assert len(chunks[2][1]) > 0 \ No newline at end of file From 888e3121ff018d8c7ae039178ac82d815b37133c Mon Sep 17 00:00:00 2001 From: Lukin Date: Sun, 1 Jun 2025 10:18:24 +0800 Subject: [PATCH 15/20] Refactor text normalization: Move handling of problematic symbols to occur after number and money processing to improve accuracy in text normalization. --- .../services/text_processing/normalizer.py | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/api/src/services/text_processing/normalizer.py b/api/src/services/text_processing/normalizer.py index 2163cbc..f439dfa 100644 --- a/api/src/services/text_processing/normalizer.py +++ b/api/src/services/text_processing/normalizer.py @@ -441,7 +441,29 @@ def normalize_text(text: str, normalization_options: NormalizationOptions) -> st text = text.replace('\n', ' ') text = text.replace('\r', ' ') - # Handle other problematic symbols + # Handle titles and abbreviations + text = re.sub(r"\bD[Rr]\.(?= [A-Z])", "Doctor", text) + text = re.sub(r"\b(?:Mr\.|MR\.(?= [A-Z]))", "Mister", text) + text = re.sub(r"\b(?:Ms\.|MS\.(?= [A-Z]))", "Miss", text) + text = re.sub(r"\b(?:Mrs\.|MRS\.(?= [A-Z]))", "Mrs", text) + text = re.sub(r"\betc\.(?! [A-Z])", "etc", text) + + # Handle common words + text = re.sub(r"(?i)\b(y)eah?\b", r"\1e'a", text) + + # Handle numbers and money BEFORE replacing special characters + text = re.sub(r"(?<=\d),(?=\d)", "", text) + + text = MONEY_PATTERN.sub( + handle_money, + text, + ) + + text = NUMBER_PATTERN.sub(handle_numbers, text) + + text = re.sub(r"\d*\.\d+", handle_decimal, text) + + # Handle other problematic symbols AFTER money/number processing text = text.replace('~', '') # Remove tilde text = text.replace('@', ' at ') # At symbol text = text.replace('#', ' number ') # Hash/pound @@ -457,28 +479,6 @@ def normalize_text(text: str, normalization_options: NormalizationOptions) -> st text = text.replace('=', ' equals ') # Equals sign text = text.replace('+', ' plus ') # Plus sign - # Handle titles and abbreviations - text = re.sub(r"\bD[Rr]\.(?= [A-Z])", "Doctor", text) - text = re.sub(r"\b(?:Mr\.|MR\.(?= [A-Z]))", "Mister", text) - text = re.sub(r"\b(?:Ms\.|MS\.(?= [A-Z]))", "Miss", text) - text = re.sub(r"\b(?:Mrs\.|MRS\.(?= [A-Z]))", "Mrs", text) - text = re.sub(r"\betc\.(?! [A-Z])", "etc", text) - - # Handle common words - text = re.sub(r"(?i)\b(y)eah?\b", r"\1e'a", text) - - # Handle numbers and money - text = re.sub(r"(?<=\d),(?=\d)", "", text) - - text = MONEY_PATTERN.sub( - handle_money, - text, - ) - - text = NUMBER_PATTERN.sub(handle_numbers, text) - - text = re.sub(r"\d*\.\d+", handle_decimal, text) - # Handle various formatting text = re.sub(r"(?<=\d)-(?=\d)", " to ", text) text = re.sub(r"(?<=\d)S", " S", text) From 0b2260602ad4e12ac91c381d4f33942db25e6743 Mon Sep 17 00:00:00 2001 From: Lukin Date: Sun, 1 Jun 2025 10:28:35 +0800 Subject: [PATCH 16/20] Update TTS service tests: Enhance test_get_voice_path_combined by mocking os.path.join to ensure correct path generation for combined voices. --- api/tests/test_tts_service.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/api/tests/test_tts_service.py b/api/tests/test_tts_service.py index ae8447a..23b5273 100644 --- a/api/tests/test_tts_service.py +++ b/api/tests/test_tts_service.py @@ -3,6 +3,7 @@ from unittest.mock import AsyncMock, MagicMock, patch import numpy as np import pytest import torch +import os from api.src.services.tts_service import TTSService @@ -93,17 +94,20 @@ async def test_get_voice_path_combined(): patch("torch.load") as mock_load, patch("torch.save") as mock_save, patch("tempfile.gettempdir") as mock_temp, + patch("os.path.join") as mock_join, ): mock_get_model.return_value = model_manager mock_get_voice.return_value = voice_manager mock_temp.return_value = "/tmp" + mock_join.return_value = "/tmp/voice1+voice2.pt" mock_load.return_value = torch.ones(10) service = await TTSService.create("test_output") name, path = await service._get_voices_path("voice1+voice2") assert name == "voice1+voice2" - assert path.endswith("voice1+voice2.pt") + assert path == "/tmp/voice1+voice2.pt" mock_save.assert_called_once() + mock_join.assert_called_with("/tmp", "voice1+voice2.pt") @pytest.mark.asyncio From f7fb9c524a0a2d362fce0631867d8c92f30472db Mon Sep 17 00:00:00 2001 From: Lukin Date: Sun, 1 Jun 2025 10:35:59 +0800 Subject: [PATCH 17/20] Refactor TTS service tests: Update test_get_voice_path_combined to verify path format for combined voices, removing mock for os.path.join and enhancing assertions for path validation. --- api/tests/test_tts_service.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/tests/test_tts_service.py b/api/tests/test_tts_service.py index 23b5273..968c31f 100644 --- a/api/tests/test_tts_service.py +++ b/api/tests/test_tts_service.py @@ -94,20 +94,20 @@ async def test_get_voice_path_combined(): patch("torch.load") as mock_load, patch("torch.save") as mock_save, patch("tempfile.gettempdir") as mock_temp, - patch("os.path.join") as mock_join, ): mock_get_model.return_value = model_manager mock_get_voice.return_value = voice_manager mock_temp.return_value = "/tmp" - mock_join.return_value = "/tmp/voice1+voice2.pt" mock_load.return_value = torch.ones(10) service = await TTSService.create("test_output") name, path = await service._get_voices_path("voice1+voice2") assert name == "voice1+voice2" - assert path == "/tmp/voice1+voice2.pt" + # Verify the path points to a temporary file with expected format + assert path.startswith("/tmp/") + assert "voice1+voice2" in path + assert path.endswith(".pt") mock_save.assert_called_once() - mock_join.assert_called_with("/tmp", "voice1+voice2.pt") @pytest.mark.asyncio From d7d90cdc9d232c36d117deb2b3ffb37b82413fda Mon Sep 17 00:00:00 2001 From: Fireblade2534 Date: Thu, 12 Jun 2025 16:00:06 +0000 Subject: [PATCH 18/20] simplified some normalization and added more tests --- api/src/services/streaming_audio_writer.py | 4 +-- .../services/text_processing/normalizer.py | 36 +++++++++++-------- .../services/text_processing/phonemizer.py | 10 +----- .../text_processing/text_processor.py | 8 ++--- api/src/structures/schemas.py | 5 +++ api/tests/test_normalizer.py | 16 +++++++++ api/tests/test_text_processor.py | 27 ++++++++++++++ 7 files changed, 77 insertions(+), 29 deletions(-) diff --git a/api/src/services/streaming_audio_writer.py b/api/src/services/streaming_audio_writer.py index 85740aa..de9c84e 100644 --- a/api/src/services/streaming_audio_writer.py +++ b/api/src/services/streaming_audio_writer.py @@ -47,12 +47,12 @@ class StreamingAudioWriter: ) self.stream = self.container.add_stream( codec_map[self.format], - rate=self.sample_rate, # Correct parameter name is 'rate' + rate=self.sample_rate, layout="mono" if self.channels == 1 else "stereo", ) # Set bit_rate only for codecs where it's applicable and useful if self.format in ['mp3', 'aac', 'opus']: - self.stream.bit_rate = 128000 # Example bitrate, can be configured + self.stream.bit_rate = 128000 else: raise ValueError(f"Unsupported format: {self.format}") # Use self.format here diff --git a/api/src/services/text_processing/normalizer.py b/api/src/services/text_processing/normalizer.py index f439dfa..7908318 100644 --- a/api/src/services/text_processing/normalizer.py +++ b/api/src/services/text_processing/normalizer.py @@ -134,6 +134,23 @@ VALID_UNITS = { "px": "pixel", # CSS units } +SYMBOL_REPLACEMENTS = { + '~': ' ', + '@': ' at ', + '#': ' number ', + '$': ' dollar ', + '%': ' percent ', + '^': ' ', + '&': ' and ', + '*': ' ', + '_': ' ', + '|': ' ', + '\\': ' ', + '/': ' slash ', + '=': ' equals ', + '+': ' plus ', +} + MONEY_UNITS = {"$": ("dollar", "cent"), "£": ("pound", "pence"), "€": ("euro", "cent")} # Pre-compiled regex patterns for performance @@ -464,20 +481,9 @@ def normalize_text(text: str, normalization_options: NormalizationOptions) -> st text = re.sub(r"\d*\.\d+", handle_decimal, text) # Handle other problematic symbols AFTER money/number processing - text = text.replace('~', '') # Remove tilde - text = text.replace('@', ' at ') # At symbol - text = text.replace('#', ' number ') # Hash/pound - text = text.replace('$', ' dollar ') # Dollar sign (if not handled by money pattern) - text = text.replace('%', ' percent ') # Percent sign - text = text.replace('^', '') # Caret - text = text.replace('&', ' and ') # Ampersand - text = text.replace('*', '') # Asterisk - text = text.replace('_', ' ') # Underscore to space - text = text.replace('|', ' ') # Pipe to space - text = text.replace('\\', ' ') # Backslash to space - text = text.replace('/', ' slash ') # Forward slash to space (unless in URLs) - text = text.replace('=', ' equals ') # Equals sign - text = text.replace('+', ' plus ') # Plus sign + if normalization_options.replace_remaining_symbols: + for symbol, replacement in SYMBOL_REPLACEMENTS.items(): + text = text.replace(symbol, replacement) # Handle various formatting text = re.sub(r"(?<=\d)-(?=\d)", " to ", text) @@ -489,4 +495,6 @@ def normalize_text(text: str, normalization_options: NormalizationOptions) -> st ) text = re.sub(r"(?i)(?<=[A-Z])\.(?=[A-Z])", "-", text) + text = re.sub(r"\s{2,}", " ", text) + return text.strip() diff --git a/api/src/services/text_processing/phonemizer.py b/api/src/services/text_processing/phonemizer.py index ae49cd9..dabf328 100644 --- a/api/src/services/text_processing/phonemizer.py +++ b/api/src/services/text_processing/phonemizer.py @@ -84,13 +84,12 @@ def create_phonemizer(language: str = "a") -> PhonemizerBackend: return EspeakBackend(lang_map[language]) -def phonemize(text: str, language: str = "a", normalize: bool = True) -> str: +def phonemize(text: str, language: str = "a") -> str: """Convert text to phonemes Args: text: Text to convert to phonemes language: Language code ('a' for US English, 'b' for British English) - normalize: Whether to normalize text before phonemization Returns: Phonemized text @@ -100,13 +99,6 @@ def phonemize(text: str, language: str = "a", normalize: bool = True) -> str: # Strip input text first to remove problematic leading/trailing spaces text = text.strip() - if normalize: - # Create default normalization options and normalize text - normalization_options = NormalizationOptions() - text = normalize_text(text, normalization_options) - # Strip again after normalization - text = text.strip() - if language not in phonemizers: phonemizers[language] = create_phonemizer(language) diff --git a/api/src/services/text_processing/text_processor.py b/api/src/services/text_processing/text_processor.py index c5a442d..39b0d6c 100644 --- a/api/src/services/text_processing/text_processor.py +++ b/api/src/services/text_processing/text_processor.py @@ -52,7 +52,7 @@ def process_text_chunk( t1 = time.time() t0 = time.time() - phonemes = phonemize(text, language, normalize=False) # Already normalized + phonemes = phonemize(text, language) # Strip phonemes result to ensure no extra spaces phonemes = phonemes.strip() t1 = time.time() @@ -102,11 +102,11 @@ def process_text(text: str, language: str = "a") -> List[int]: def get_sentence_info( text: str, custom_phenomes_list: Dict[str, str], lang_code: str = "a" ) -> List[Tuple[str, List[int], int]]: - """Process all sentences and return info, 支持中文分句""" - # 判断是否为中文 + """Process all sentences and return info""" + # Detect Chinese text is_chinese = lang_code.startswith("z") or re.search(r"[\u4e00-\u9fff]", text) if is_chinese: - # 按中文标点断句 + # Split using Chinese punctuation sentences = re.split(r"([,。!?;])+", text) else: sentences = re.split(r"([.!?;:])(?=\s|$)", text) diff --git a/api/src/structures/schemas.py b/api/src/structures/schemas.py index 260224c..83b1c0b 100644 --- a/api/src/structures/schemas.py +++ b/api/src/structures/schemas.py @@ -1,3 +1,4 @@ +from email.policy import default from enum import Enum from typing import List, Literal, Optional, Union @@ -66,6 +67,10 @@ class NormalizationOptions(BaseModel): default=True, description="Changes phone numbers so they can be properly pronouced by kokoro", ) + replace_remaining_symbols: bool = Field( + default=True, + description="Replaces the remaining symbols after normalization with their words" + ) class OpenAISpeechRequest(BaseModel): diff --git a/api/tests/test_normalizer.py b/api/tests/test_normalizer.py index 3db0801..6b5a8bf 100644 --- a/api/tests/test_normalizer.py +++ b/api/tests/test_normalizer.py @@ -175,6 +175,13 @@ def test_money(): == "The plant cost two hundred thousand dollars and eighty cents." ) + assert ( + normalize_text( + "Your shopping spree cost $674.03!", normalization_options=NormalizationOptions() + ) + == "Your shopping spree cost six hundred and seventy-four dollars and three cents!" + ) + assert ( normalize_text( "€30.2 is in euros", normalization_options=NormalizationOptions() @@ -315,3 +322,12 @@ def test_non_url_text(): normalize_text("It costs $50.", normalization_options=NormalizationOptions()) == "It costs fifty dollars." ) + +def test_remaining_symbol(): + """Test that remaining symbols are replaced""" + assert ( + normalize_text( + "I love buying products @ good store here & @ other store", normalization_options=NormalizationOptions() + ) + == "I love buying products at good store here and at other store" + ) diff --git a/api/tests/test_text_processor.py b/api/tests/test_text_processor.py index 95c0259..7495d1d 100644 --- a/api/tests/test_text_processor.py +++ b/api/tests/test_text_processor.py @@ -194,4 +194,31 @@ async def test_smart_split_with_pause(): # Third chunk: text assert chunks[2][2] is None # No pause assert "How are you?" in chunks[2][0] + assert len(chunks[2][1]) > 0 + +@pytest.mark.asyncio +async def test_smart_split_with_two_pause(): + """Test smart splitting with two pause tags.""" + text = "[pause:0.5s][pause:1.67s]0.5" + + chunks = [] + async for chunk_text, chunk_tokens, pause_duration in smart_split(text): + chunks.append((chunk_text, chunk_tokens, pause_duration)) + + # Should have 3 chunks: pause, pause, text + assert len(chunks) == 3 + + # First chunk: pause + assert chunks[0][2] == 0.5 # 0.5 second pause + assert chunks[0][0] == "" # Empty text + assert len(chunks[0][1]) == 0 + + # Second chunk: pause + assert chunks[1][2] == 1.67 # 1.67 second pause + assert chunks[1][0] == "" # Empty text + assert len(chunks[1][1]) == 0 # No tokens + + # Third chunk: text + assert chunks[2][2] is None # No pause + assert "zero point five" in chunks[2][0] assert len(chunks[2][1]) > 0 \ No newline at end of file From cd82dd07355fca75a9cb37e75da624a0d3b3d0ae Mon Sep 17 00:00:00 2001 From: Fireblade2534 Date: Mon, 16 Jun 2025 16:39:30 +0000 Subject: [PATCH 19/20] Added a volume multiplier as a request parameter --- api/src/core/config.py | 2 +- api/src/inference/model_manager.py | 4 ++-- api/src/routers/development.py | 1 + api/src/routers/openai_compatible.py | 2 ++ api/src/services/tts_service.py | 11 ++++++++++- api/src/structures/schemas.py | 8 ++++++++ 6 files changed, 24 insertions(+), 4 deletions(-) diff --git a/api/src/core/config.py b/api/src/core/config.py index 3bc825c..87edce0 100644 --- a/api/src/core/config.py +++ b/api/src/core/config.py @@ -31,7 +31,7 @@ class Settings(BaseSettings): # Audio Settings sample_rate: int = 24000 - volume_multiplier: float = 1.0 + default_volume_multiplier: float = 1.0 # Text Processing Settings target_min_tokens: int = 175 # Target minimum tokens per chunk target_max_tokens: int = 250 # Target maximum tokens per chunk diff --git a/api/src/inference/model_manager.py b/api/src/inference/model_manager.py index 0b4cd81..eb817ec 100644 --- a/api/src/inference/model_manager.py +++ b/api/src/inference/model_manager.py @@ -141,8 +141,8 @@ Model files not found! You need to download the Kokoro V1 model: try: async for chunk in self._backend.generate(*args, **kwargs): - if settings.volume_multiplier != 1.0: - chunk.audio *= settings.volume_multiplier + if settings.default_volume_multiplier != 1.0: + chunk.audio *= settings.default_volume_multiplier yield chunk except Exception as e: raise RuntimeError(f"Generation failed: {e}") diff --git a/api/src/routers/development.py b/api/src/routers/development.py index d78aa3c..8c8ed7e 100644 --- a/api/src/routers/development.py +++ b/api/src/routers/development.py @@ -319,6 +319,7 @@ async def create_captioned_speech( writer=writer, speed=request.speed, return_timestamps=request.return_timestamps, + volume_multiplier=request.volume_multiplier, normalization_options=request.normalization_options, lang_code=request.lang_code, ) diff --git a/api/src/routers/openai_compatible.py b/api/src/routers/openai_compatible.py index 4819bc5..c325221 100644 --- a/api/src/routers/openai_compatible.py +++ b/api/src/routers/openai_compatible.py @@ -152,6 +152,7 @@ async def stream_audio_chunks( speed=request.speed, output_format=request.response_format, lang_code=request.lang_code, + volume_multiplier=request.volume_multiplier, normalization_options=request.normalization_options, return_timestamps=unique_properties["return_timestamps"], ): @@ -300,6 +301,7 @@ async def create_speech( voice=voice_name, writer=writer, speed=request.speed, + volume_multiplier=request.volume_multiplier, normalization_options=request.normalization_options, lang_code=request.lang_code, ) diff --git a/api/src/services/tts_service.py b/api/src/services/tts_service.py index 0a69b85..dca0d02 100644 --- a/api/src/services/tts_service.py +++ b/api/src/services/tts_service.py @@ -55,6 +55,7 @@ class TTSService: output_format: Optional[str] = None, is_first: bool = False, is_last: bool = False, + volume_multiplier: Optional[float] = 1.0, normalizer: Optional[AudioNormalizer] = None, lang_code: Optional[str] = None, return_timestamps: Optional[bool] = False, @@ -100,6 +101,7 @@ class TTSService: lang_code=lang_code, return_timestamps=return_timestamps, ): + chunk_data.audio*=volume_multiplier # For streaming, convert to bytes if output_format: try: @@ -132,7 +134,7 @@ class TTSService: speed=speed, return_timestamps=return_timestamps, ) - + if chunk_data.audio is None: logger.error("Model generated None for audio chunk") return @@ -141,6 +143,8 @@ class TTSService: logger.error("Model generated empty audio chunk") return + chunk_data.audio*=volume_multiplier + # For streaming, convert to bytes if output_format: try: @@ -259,6 +263,7 @@ class TTSService: speed: float = 1.0, output_format: str = "wav", lang_code: Optional[str] = None, + volume_multiplier: Optional[float] = 1.0, normalization_options: Optional[NormalizationOptions] = NormalizationOptions(), return_timestamps: Optional[bool] = False, ) -> AsyncGenerator[AudioChunk, None]: @@ -298,6 +303,7 @@ class TTSService: output_format, is_first=(chunk_index == 0), is_last=False, # We'll update the last chunk later + volume_multiplier=volume_multiplier, normalizer=stream_normalizer, lang_code=pipeline_lang_code, # Pass lang_code return_timestamps=return_timestamps, @@ -337,6 +343,7 @@ class TTSService: output_format, is_first=False, is_last=True, # Signal this is the last chunk + volume_multiplier=volume_multiplier, normalizer=stream_normalizer, lang_code=pipeline_lang_code, # Pass lang_code ): @@ -356,6 +363,7 @@ class TTSService: writer: StreamingAudioWriter, speed: float = 1.0, return_timestamps: bool = False, + volume_multiplier: Optional[float] = 1.0, normalization_options: Optional[NormalizationOptions] = NormalizationOptions(), lang_code: Optional[str] = None, ) -> AudioChunk: @@ -368,6 +376,7 @@ class TTSService: voice, writer, speed=speed, + volume_multiplier=volume_multiplier, normalization_options=normalization_options, return_timestamps=return_timestamps, lang_code=lang_code, diff --git a/api/src/structures/schemas.py b/api/src/structures/schemas.py index 260224c..f8273cc 100644 --- a/api/src/structures/schemas.py +++ b/api/src/structures/schemas.py @@ -108,6 +108,10 @@ class OpenAISpeechRequest(BaseModel): default=None, description="Optional language code to use for text processing. If not provided, will use first letter of voice name.", ) + volume_multiplier: Optional[float] = Field( + default = 1.0, + description="A volume multiplier to multiply the output audio by." + ) normalization_options: Optional[NormalizationOptions] = Field( default=NormalizationOptions(), description="Options for the normalization system", @@ -152,6 +156,10 @@ class CaptionedSpeechRequest(BaseModel): default=None, description="Optional language code to use for text processing. If not provided, will use first letter of voice name.", ) + volume_multiplier: Optional[float] = Field( + default = 1.0, + description="A volume multiplier to multiply the output audio by." + ) normalization_options: Optional[NormalizationOptions] = Field( default=NormalizationOptions(), description="Options for the normalization system", From ac491a9b1820f32b3cf5a3b6fffc30972b1e0b44 Mon Sep 17 00:00:00 2001 From: Fireblade2534 Date: Wed, 18 Jun 2025 22:02:33 +0000 Subject: [PATCH 20/20] Release --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 0d91a54..72f9fa8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.3.0 +0.2.4 \ No newline at end of file