[Bugfix] Fix Qwen3-TTS word timestamps with async chunking (#7544)

Signed-off-by: bezdarnost <amanurumbekov@gmail.com>
This commit is contained in:
Aman authored and GitHub committed 2026-09-16 15:07:52 -07:00
1 parent 63032c91c6
commit c32aaeb2da
18 files changed
+459 -13

No files matched your search

@@ -5212,6 +5212,52 @@ class TestTTSAsyncOffloading:
for call in log_info.call_args_list
)
@pytest.mark.parametrize("word_timestamps", [False, True])
def test_streaming_timestamps_retain_complete_audio(self, qwen3_tts_server, mocker, word_timestamps):
from vllm import SamplingParams
from vllm.sampling_params import RequestOutputKind
defaults = [SamplingParams(), SamplingParams()]
qwen3_tts_server.engine_client.default_sampling_params_list = defaults
qwen3_tts_server._adapter.validate = mocker.MagicMock(return_value=None)
qwen3_tts_server._adapter._build_tts_params = mocker.MagicMock(
return_value={"text": ["hello"], "task_type": ["CustomVoice"], "speaker": ["Vivian"]}
)
qwen3_tts_server._adapter._estimate_prompt_len_async = mocker.AsyncMock(return_value=512)
request = OpenAICreateSpeechRequest(
input="hello", stream=True, response_format="pcm", word_timestamps=word_timestamps
)
asyncio.run(qwen3_tts_server._prepare_speech_generation(request))
params = qwen3_tts_server.engine_client.generate.call_args.kwargs["sampling_params_list"]
expected = RequestOutputKind.CUMULATIVE if word_timestamps else RequestOutputKind.DELTA
assert all(sp.output_kind == expected for sp in params)
assert all(sp.output_kind == RequestOutputKind.CUMULATIVE for sp in defaults)
assert all(sp is not original for sp, original in zip(params, defaults))
@pytest.mark.asyncio
async def test_cumulative_timestamp_audio_emits_each_sample_once(self, qwen3_tts_server):
audio = torch.linspace(-0.5, 0.5, 2400)
async def cumulative_generator():
for end in (800, 1600, 2400, 2400):
yield OmniRequestOutput(
request_id="req-cumulative",
final_output_type="audio",
_multimodal_output={"audio": audio[:end], "sr": 24000},
)
chunks = [
chunk
async for chunk in qwen3_tts_server._generate_pcm_chunks(
cumulative_generator(), "req-cumulative", cumulative_audio=True
)
]
assert len(chunks) == 3
assert len(b"".join(chunks)) == 2400 * 2
decoded = np.frombuffer(b"".join(chunks), dtype=np.int16)
assert np.all(np.diff(decoded.astype(np.int32)) >= 0)
def test_prepare_speech_generation_treats_sse_as_streaming(self, qwen3_tts_server, mocker: MockerFixture):
"""stream_format=sse should request delta-style multimodal outputs."""
qwen3_tts_server._adapter.validate = mocker.MagicMock(return_value=None)