Repository: coqui-ai/TTS

Issue:
[Bug] Exception while using "--speaker_wav"
<!-- Welcome to the 🐸TTS!
We are excited to see your interest, and appreciate your support! --->
## 🐛 Description

<!-- Exception while using "--speaker_wav" -->

(base) root@ip-192-168-0-200:/

/root/miniconda3/bin/tts --text "Awesome, Pretty Good" --model_name "tts_models/en/vctk/vits" --out_path "chunk11_encoded.wav" --speaker_wav "chunk10.wav"


 > tts_models/en/vctk/vits is already downloaded.
 > Using model: vits
 > Setting up Audio Processor...
 | > sample_rate:22050
 | > resample:False
 | > num_mels:80
 | > log_func:np.log10
 | > min_level_db:-100
 | > frame_shift_ms:None
 | > frame_length_ms:None
 | > ref_level_db:20
 | > fft_size:1024
 | > power:1.5
 | > preemphasis:0.0
 | > griffin_lim_iters:60
 | > signal_norm:True
 | > symmetric_norm:True
 | > mel_fmin:0
 | > mel_fmax:None
 | > pitch_fmin:0.0
 | > pitch_fmax:640.0
 | > spec_gain:20.0
 | > stft_pad_mode:reflect
 | > max_norm:4.0
 | > clip_norm:True
 | > do_trim_silence:True
 | > trim_db:45
 | > do_sound_norm:False
 | > do_amp_to_db_linear:False
 | > do_amp_to_db_mel:True
 | > do_rms_norm:False
 | > db_level:None
 | > stats_path:None
 | > base:10
 | > hop_length:256
 | > win_length:1024
 > initialization of speaker-embedding layers.
 > Using Griffin-Lim as no vocoder model defined
 > Text: Awesome, Pretty Good
 > Text splitted to sentences.
['Awesome, Pretty Good']
Traceback (most recent call last):
  File "/root/miniconda3/bin/tts", line 8, in <module>
    sys.exit(main())
  File "/root/miniconda3/lib/python3.9/site-packages/TTS/bin/synthesize.py", line 287, in main
    wav = synthesizer.tts(args.text, args.speaker_idx, args.language_idx, args.speaker_wav)
  File "/root/miniconda3/lib/python3.9/site-packages/TTS/utils/synthesizer.py", line 245, in tts
    speaker_embedding = self.tts_model.speaker_manager.compute_d_vector_from_clip(speaker_wav)
  File "/root/miniconda3/lib/python3.9/site-packages/TTS/tts/utils/speakers.py", line 287, in compute_d_vector_from_clip
    d_vector = _compute(wf)
  File "/root/miniconda3/lib/python3.9/site-packages/TTS/tts/utils/speakers.py", line 270, in _compute
    waveform = self.speaker_encoder_ap.load_wav(wav_file, sr=self.speaker_encoder_ap.sample_rate)
AttributeError: 'NoneType' object has no attribute 'load_wav'



<!--
Please share your code to reproduce the error. Issues fixed faster if you can provide a working example.

The best place for sharing code is colab. https://colab.research.google.com/
So we can directly run your code and reproduce the issue.

In the worse case provide steps to reproduce the behaviour.

1. Run the following command '...'
2. ...
3. See error
-->

### Expected behavior

<!-- Write down what the expected behaviour -->

### Environment

<!--
You can either run `TTS/bin/collect_env_info.py`

```bash
wget https://raw.githubusercontent.com/coqui-ai/TTS/main/TTS/bin/collect_env_info.py
python collect_env_info.py
```

or fill in the fields below manually.
-->

- 🐸TTS Version (e.g., 1.3.0):
- PyTorch Version (e.g., 1.8)
- Python version:
- OS (e.g., Linux):
- CUDA/cuDNN version:
- GPU models and configuration:
- How you installed PyTorch (`conda`, `pip`, source):
- Any other relevant information:

### Additional context

<!-- Add any other context about the problem here. -->



Discussion:
Hey, that's not a bug. The model `tts_models/en/vctk/vits` doesn't use an external speaker embedding, you can only use the speakers it was trained on. You can see thoses speakers here `tts --model_name "tts_models/en/vctk/vits" --list_speaker_idx`.

To use clone someone voice with `--speaker_wav` you can use YourTTS `tts_models/multilingual/multi-dataset/your_tts`
If you have more questions about this, feel free to reopen the issue, or ask them on our [Gitter](https://gitter.im/coqui-ai/TTS?utm_source=share-link&utm_medium=link&utm_campaign=share-link).
Heya @WeberJulian -- maybe a more informative error message would be useful here? Since this isn't really an error - otherwise it looks like a bug

Resolving patch:
diff --git a/TTS/api.py b/TTS/api.py
--- a/TTS/api.py
+++ b/TTS/api.py
@@ -440,7 +440,7 @@ def voice_conversion_to_file(
         save_wav(wav=wav, path=file_path, sample_rate=self.voice_converter.vc_config.audio.output_sample_rate)
         return file_path
 
-    def tts_with_vc(self, text: str, language: str = None, speaker_wav: str = None):
+    def tts_with_vc(self, text: str, language: str = None, speaker_wav: str = None, speaker: str = None):
         """Convert text to speech with voice conversion.
 
         It combines tts with voice conversion to fake voice cloning.
@@ -457,17 +457,25 @@ def tts_with_vc(self, text: str, language: str = None, speaker_wav: str = None):
             speaker_wav (str, optional):
                 Path to a reference wav file to use for voice cloning with supporting models like YourTTS.
                 Defaults to None.
+            speaker (str, optional):
+                Speaker name for multi-speaker. You can check whether loaded model is multi-speaker by
+                `tts.is_multi_speaker` and list speakers by `tts.speakers`. Defaults to None.
         """
         with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as fp:
             # Lazy code... save it to a temp file to resample it while reading it for VC
-            self.tts_to_file(text=text, speaker=None, language=language, file_path=fp.name, speaker_wav=speaker_wav)
+            self.tts_to_file(text=text, speaker=speaker, language=language, file_path=fp.name)
         if self.voice_converter is None:
             self.load_vc_model_by_name("voice_conversion_models/multilingual/vctk/freevc24")
         wav = self.voice_converter.voice_conversion(source_wav=fp.name, target_wav=speaker_wav)
         return wav
 
     def tts_with_vc_to_file(
-        self, text: str, language: str = None, speaker_wav: str = None, file_path: str = "output.wav"
+        self,
+        text: str,
+        language: str = None,
+        speaker_wav: str = None,
+        file_path: str = "output.wav",
+        speaker: str = None,
     ):
         """Convert text to speech with voice conversion and save to file.
 
@@ -484,6 +492,9 @@ def tts_with_vc_to_file(
                 Defaults to None.
             file_path (str, optional):
                 Output file path. Defaults to "output.wav".
+            speaker (str, optional):
+                Speaker name for multi-speaker. You can check whether loaded model is multi-speaker by
+                `tts.is_multi_speaker` and list speakers by `tts.speakers`. Defaults to None.
         """
-        wav = self.tts_with_vc(text=text, language=language, speaker_wav=speaker_wav)
+        wav = self.tts_with_vc(text=text, language=language, speaker_wav=speaker_wav, speaker=speaker)
         save_wav(wav=wav, path=file_path, sample_rate=self.voice_converter.vc_config.audio.output_sample_rate)
diff --git a/TTS/utils/synthesizer.py b/TTS/utils/synthesizer.py
--- a/TTS/utils/synthesizer.py
+++ b/TTS/utils/synthesizer.py
@@ -358,7 +358,11 @@ def tts(
                 )
 
         # compute a new d_vector from the given clip.
-        if speaker_wav is not None and self.tts_model.speaker_manager is not None:
+        if (
+            speaker_wav is not None
+            and self.tts_model.speaker_manager is not None
+            and self.tts_model.speaker_manager.encoder_ap is not None
+        ):
             speaker_embedding = self.tts_model.speaker_manager.compute_embedding_from_clip(speaker_wav)
 
         vocoder_device = "cpu"


Test patch: