@@ -1318,7 +1318,57 @@ def test_elevenlabs_api_key_matches_music_service(self):
13181318 )
13191319
13201320
1321+ def test_siliconflow_subtitle_spans_full_audio_duration (self ):
1322+ """Last subtitle entry must end at the actual audio end, not truncated early.
1323+
1324+ The old ad-hoc loop applied integer division independently to every
1325+ sentence, so accumulated truncation meant the final subtitle always
1326+ ended a few units before the real audio end. Every other TTS provider
1327+ already delegates to populate_legacy_submaker_with_full_text, which
1328+ anchors the last entry to the full duration; this test verifies
1329+ siliconflow_tts now does the same.
1330+ """
1331+ audio_duration_seconds = 7.3
1332+ expected_end_100ns = int (audio_duration_seconds * 10_000_000 )
1333+
1334+ fake_response = SimpleNamespace (status_code = 200 , content = b"fake-mp3" )
1335+ fake_clip = SimpleNamespace (
1336+ duration = audio_duration_seconds , close = lambda : None
1337+ )
1338+
1339+ with (
1340+ tempfile .TemporaryDirectory () as tmp_dir ,
1341+ patch .object (vs .requests , "post" , return_value = fake_response ),
1342+ patch .object (vs , "AudioFileClip" , return_value = fake_clip ),
1343+ patch .object (vs .config , "siliconflow" , {"api_key" : "test-key" }),
1344+ ):
1345+ voice_file = str (Path (tmp_dir ) / "test.mp3" )
1346+ sub_maker = vs .siliconflow_tts (
1347+ text = (
1348+ "First sentence. Second sentence. "
1349+ "Third sentence. Fourth sentence."
1350+ ),
1351+ model = "FunAudioLLM/CosyVoice2-0.5B" ,
1352+ voice = "FunAudioLLM/CosyVoice2-0.5B:alex" ,
1353+ voice_rate = 1.0 ,
1354+ voice_file = voice_file ,
1355+ )
1356+
1357+ self .assertIsNotNone (sub_maker )
1358+ offsets = getattr (sub_maker , "offset" , [])
1359+ self .assertGreater (
1360+ len (offsets ), 1 , "multi-sentence text must produce multiple subtitles"
1361+ )
1362+ last_end = offsets [- 1 ][1 ]
1363+ self .assertEqual (
1364+ last_end ,
1365+ expected_end_100ns ,
1366+ f"last subtitle end ({ last_end } ) must equal the full audio duration "
1367+ f"({ expected_end_100ns } units = { audio_duration_seconds } s)" ,
1368+ )
1369+
1370+
13211371if __name__ == "__main__" :
13221372 # python -m unittest test.services.test_voice.TestVoiceService.test_azure_tts_v1
13231373 # python -m unittest test.services.test_voice.TestVoiceService.test_azure_tts_v2
1324- unittest .main ()
1374+ unittest .main ()
0 commit comments