mirror of
https://github.com/neuml/txtai.git
synced 2026-10-11 21:39:55 +00:00
This commit is contained in:
@@ -92,7 +92,7 @@ class TextToSpeech(Pipeline):
|
|||||||
|
|
||||||
# Streaming response
|
# Streaming response
|
||||||
if stream:
|
if stream:
|
||||||
return self.stream(texts, speaker, encoding)
|
return self.stream(texts, speaker, encoding, **kwargs)
|
||||||
|
|
||||||
# Transform text to speech
|
# Transform text to speech
|
||||||
results = [self.execute(x, speaker, encoding, **kwargs) for x in texts]
|
results = [self.execute(x, speaker, encoding, **kwargs) for x in texts]
|
||||||
@@ -137,7 +137,7 @@ class TextToSpeech(Pipeline):
|
|||||||
|
|
||||||
return exists
|
return exists
|
||||||
|
|
||||||
def stream(self, texts, speaker, encoding):
|
def stream(self, texts, speaker, encoding, **kwargs):
|
||||||
"""
|
"""
|
||||||
Iterates over texts, splits into segments and yields snippets of audio.
|
Iterates over texts, splits into segments and yields snippets of audio.
|
||||||
This method is designed to integrate with streaming LLM generation.
|
This method is designed to integrate with streaming LLM generation.
|
||||||
@@ -146,6 +146,7 @@ class TextToSpeech(Pipeline):
|
|||||||
texts: list of input texts
|
texts: list of input texts
|
||||||
speaker: speaker id
|
speaker: speaker id
|
||||||
encoding: audio encoding format
|
encoding: audio encoding format
|
||||||
|
kwargs: additional keyword args
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
snippets of audio as NumPy arrays or audio bytes depending on encoding parameter
|
snippets of audio as NumPy arrays or audio bytes depending on encoding parameter
|
||||||
@@ -157,11 +158,11 @@ class TextToSpeech(Pipeline):
|
|||||||
|
|
||||||
if x == "\n" or (x.strip().endswith(".") and len([y for y in buffer if y]) > 2):
|
if x == "\n" or (x.strip().endswith(".") and len([y for y in buffer if y]) > 2):
|
||||||
data, buffer = "".join(buffer), []
|
data, buffer = "".join(buffer), []
|
||||||
yield self.execute(data, speaker, encoding)
|
yield self.execute(data, speaker, encoding, **kwargs)
|
||||||
|
|
||||||
if buffer:
|
if buffer:
|
||||||
data = "".join(buffer)
|
data = "".join(buffer)
|
||||||
yield self.execute(data, speaker, encoding)
|
yield self.execute(data, speaker, encoding, **kwargs)
|
||||||
|
|
||||||
def execute(self, text, speaker, encoding, **kwargs):
|
def execute(self, text, speaker, encoding, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ TextToSpeech module tests
|
|||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from unittest.mock import patch
|
from unittest.mock import call, patch
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
from txtai.pipeline import TextToSpeech
|
from txtai.pipeline import TextToSpeech
|
||||||
|
|
||||||
@@ -80,3 +82,26 @@ class TestTextToSpeech(unittest.TestCase):
|
|||||||
# Check that data is generated
|
# Check that data is generated
|
||||||
self.assertGreater(len(speech), 0)
|
self.assertGreater(len(speech), 0)
|
||||||
self.assertEqual(rate, 22050)
|
self.assertEqual(rate, 22050)
|
||||||
|
|
||||||
|
@patch("txtai.pipeline.audio.texttospeech.Kokoro")
|
||||||
|
@patch.object(TextToSpeech, "hasfile")
|
||||||
|
def testStreamingOptions(self, hasfile, kokoro):
|
||||||
|
"""
|
||||||
|
Test backend options reach both flushed and final streaming segments
|
||||||
|
"""
|
||||||
|
|
||||||
|
hasfile.side_effect = lambda _, name: name in ("model.onnx", "voices.json")
|
||||||
|
audio = np.array([0.1, -0.1], dtype=np.float32)
|
||||||
|
kokoro.return_value.return_value = (audio, 24000)
|
||||||
|
tts = TextToSpeech("neuml/kokoro-int8-onnx", rate=None)
|
||||||
|
|
||||||
|
chunks = list(tts(iter(["One ", "two ", "three.", "Tail"]), stream=True, speaker="af", speed=1.5, transcribe=False))
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
kokoro.return_value.call_args_list,
|
||||||
|
[call("One two three.", "af", speed=1.5, transcribe=False), call("Tail", "af", speed=1.5, transcribe=False)],
|
||||||
|
)
|
||||||
|
self.assertEqual(len(chunks), 2)
|
||||||
|
for data, rate in chunks:
|
||||||
|
np.testing.assert_array_equal(data, audio)
|
||||||
|
self.assertEqual(rate, 24000)
|
||||||
|
|||||||
Reference in New Issue
Block a user