@@ -318,7 +318,7 @@ def test_state_restoration_after_chunking(self, mock_chunker_class):
318318
319319 # Track state changes during _separate_file call
320320 state_during_processing = {}
321- def track_state (chunk_path , custom_names ):
321+ def track_state (chunk_path , custom_names = None ):
322322 state_during_processing ['chunk_duration' ] = separator .chunk_duration
323323 state_during_processing ['output_dir' ] = separator .output_dir
324324 state_during_processing ['model_output_dir' ] = separator .model_instance .output_dir
@@ -500,8 +500,13 @@ def test_audio_chunker_initialization(self, mock_chunker_class):
500500 mock_chunker_class .assert_called_once_with (15.0 , separator .logger )
501501
502502 @patch ('audio_separator.separator.audio_chunking.AudioChunker' )
503- def test_custom_output_names_parameter (self , mock_chunker_class ):
504- """Test that custom_output_names parameter is handled correctly."""
503+ def test_custom_output_names_applied_to_merged_output (self , mock_chunker_class ):
504+ """Test that custom_output_names are applied to final merged output, not per-chunk.
505+
506+ Regression test for issue #259: when custom_output_names were passed to
507+ _separate_file for each chunk, chunks would get the same custom name and
508+ overwrite each other, producing corrupted output.
509+ """
505510 # Setup mock separator
506511 separator = Mock (spec = Separator )
507512 separator .logger = self .logger
@@ -511,18 +516,25 @@ def test_custom_output_names_parameter(self, mock_chunker_class):
511516 separator .model_instance = Mock ()
512517 separator .model_instance .output_dir = self .temp_dir
513518
514- # Mock chunker behavior
519+ # Mock chunker behavior - multiple chunks to reproduce the overwrite bug
515520 mock_chunker = Mock ()
516521 mock_chunker_class .return_value = mock_chunker
517522 mock_chunker .split_audio .return_value = [
518523 os .path .join (self .temp_dir , "chunk_0000.wav" ),
524+ os .path .join (self .temp_dir , "chunk_0001.wav" ),
525+ os .path .join (self .temp_dir , "chunk_0002.wav" ),
519526 ]
520527
521- separator ._separate_file = Mock (return_value = [
522- os .path .join (self .temp_dir , "chunk_0000_(Vocals).wav" ),
528+ separator ._separate_file = Mock (side_effect = [
529+ [os .path .join (self .temp_dir , "chunk_0000_(Vocals).wav" ),
530+ os .path .join (self .temp_dir , "chunk_0000_(Instrumental).wav" )],
531+ [os .path .join (self .temp_dir , "chunk_0001_(Vocals).wav" ),
532+ os .path .join (self .temp_dir , "chunk_0001_(Instrumental).wav" )],
533+ [os .path .join (self .temp_dir , "chunk_0002_(Vocals).wav" ),
534+ os .path .join (self .temp_dir , "chunk_0002_(Instrumental).wav" )],
523535 ])
524536
525- custom_names = {"Vocals" : "my_custom_vocals" }
537+ custom_names = {"Vocals" : "my_custom_vocals" , "Instrumental" : "my_custom_instrumental" }
526538
527539 # Import and call the actual method
528540 from audio_separator .separator .separator import Separator as RealSeparator
@@ -532,9 +544,25 @@ def test_custom_output_names_parameter(self, mock_chunker_class):
532544 custom_output_names = custom_names
533545 )
534546
535- # Verify custom name was used in output
536- assert len (result ) == 1
537- assert "my_custom_vocals" in os .path .basename (result [0 ])
547+ # Verify _separate_file was called WITHOUT custom_output_names for each chunk
548+ # This is the core of the fix: chunks must use default naming to avoid overwrites
549+ for call_args in separator ._separate_file .call_args_list :
550+ args , kwargs = call_args
551+ assert len (args ) == 1 , f"_separate_file should be called with only chunk_path, got args: { args } "
552+ assert "custom_output_names" not in kwargs , \
553+ f"_separate_file should not receive custom_output_names, got kwargs: { kwargs } "
554+
555+ # Verify custom names were applied to the final merged output
556+ assert len (result ) == 2
557+ output_basenames = [os .path .basename (path ) for path in result ]
558+ assert any ("my_custom_instrumental" in name for name in output_basenames )
559+ assert any ("my_custom_vocals" in name for name in output_basenames )
560+
561+ # Verify all 3 chunks were processed for each stem
562+ assert mock_chunker .merge_chunks .call_count == 2
563+ for merge_call in mock_chunker .merge_chunks .call_args_list :
564+ chunk_list = merge_call [0 ][0 ]
565+ assert len (chunk_list ) == 3 , f"Each stem should merge 3 chunks, got { len (chunk_list )} "
538566
539567
540568class TestSeparatorChunkingEdgeCases :
0 commit comments