mirror of
https://github.com/FunAudioLLM/CosyVoice.git
synced 2026-02-04 17:39:25 +08:00
add_zero_shot_spk
This commit is contained in:
@@ -85,7 +85,6 @@ We strongly recommend that you download our pretrained `CosyVoice2-0.5B` `CosyVo
|
|||||||
from modelscope import snapshot_download
|
from modelscope import snapshot_download
|
||||||
snapshot_download('iic/CosyVoice2-0.5B', local_dir='pretrained_models/CosyVoice2-0.5B')
|
snapshot_download('iic/CosyVoice2-0.5B', local_dir='pretrained_models/CosyVoice2-0.5B')
|
||||||
snapshot_download('iic/CosyVoice-300M', local_dir='pretrained_models/CosyVoice-300M')
|
snapshot_download('iic/CosyVoice-300M', local_dir='pretrained_models/CosyVoice-300M')
|
||||||
snapshot_download('iic/CosyVoice-300M-25Hz', local_dir='pretrained_models/CosyVoice-300M-25Hz')
|
|
||||||
snapshot_download('iic/CosyVoice-300M-SFT', local_dir='pretrained_models/CosyVoice-300M-SFT')
|
snapshot_download('iic/CosyVoice-300M-SFT', local_dir='pretrained_models/CosyVoice-300M-SFT')
|
||||||
snapshot_download('iic/CosyVoice-300M-Instruct', local_dir='pretrained_models/CosyVoice-300M-Instruct')
|
snapshot_download('iic/CosyVoice-300M-Instruct', local_dir='pretrained_models/CosyVoice-300M-Instruct')
|
||||||
snapshot_download('iic/CosyVoice-ttsfrd', local_dir='pretrained_models/CosyVoice-ttsfrd')
|
snapshot_download('iic/CosyVoice-ttsfrd', local_dir='pretrained_models/CosyVoice-ttsfrd')
|
||||||
@@ -96,7 +95,6 @@ snapshot_download('iic/CosyVoice-ttsfrd', local_dir='pretrained_models/CosyVoice
|
|||||||
mkdir -p pretrained_models
|
mkdir -p pretrained_models
|
||||||
git clone https://www.modelscope.cn/iic/CosyVoice2-0.5B.git pretrained_models/CosyVoice2-0.5B
|
git clone https://www.modelscope.cn/iic/CosyVoice2-0.5B.git pretrained_models/CosyVoice2-0.5B
|
||||||
git clone https://www.modelscope.cn/iic/CosyVoice-300M.git pretrained_models/CosyVoice-300M
|
git clone https://www.modelscope.cn/iic/CosyVoice-300M.git pretrained_models/CosyVoice-300M
|
||||||
git clone https://www.modelscope.cn/iic/CosyVoice-300M-25Hz.git pretrained_models/CosyVoice-300M-25Hz
|
|
||||||
git clone https://www.modelscope.cn/iic/CosyVoice-300M-SFT.git pretrained_models/CosyVoice-300M-SFT
|
git clone https://www.modelscope.cn/iic/CosyVoice-300M-SFT.git pretrained_models/CosyVoice-300M-SFT
|
||||||
git clone https://www.modelscope.cn/iic/CosyVoice-300M-Instruct.git pretrained_models/CosyVoice-300M-Instruct
|
git clone https://www.modelscope.cn/iic/CosyVoice-300M-Instruct.git pretrained_models/CosyVoice-300M-Instruct
|
||||||
git clone https://www.modelscope.cn/iic/CosyVoice-ttsfrd.git pretrained_models/CosyVoice-ttsfrd
|
git clone https://www.modelscope.cn/iic/CosyVoice-ttsfrd.git pretrained_models/CosyVoice-ttsfrd
|
||||||
@@ -136,6 +134,11 @@ prompt_speech_16k = load_wav('./asset/zero_shot_prompt.wav', 16000)
|
|||||||
for i, j in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '希望你以后能够做的比我还好呦。', prompt_speech_16k, stream=False)):
|
for i, j in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '希望你以后能够做的比我还好呦。', prompt_speech_16k, stream=False)):
|
||||||
torchaudio.save('zero_shot_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate)
|
torchaudio.save('zero_shot_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate)
|
||||||
|
|
||||||
|
# save zero_shot spk for futher usage
|
||||||
|
assert cosyvoice.add_zero_shot_spk('希望你以后能够做的比我还好呦。', prompt_speech_16k, 'my_zero_shot_spk') is True
|
||||||
|
for i, j in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '', '', zero_shot_spk_id='my_zero_shot_spk', stream=False)):
|
||||||
|
torchaudio.save('zero_shot_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate)
|
||||||
|
|
||||||
# fine grained control, for supported control, check cosyvoice/tokenizer/tokenizer.py#L248
|
# fine grained control, for supported control, check cosyvoice/tokenizer/tokenizer.py#L248
|
||||||
for i, j in enumerate(cosyvoice.inference_cross_lingual('在他讲述那个荒诞故事的过程中,他突然[laughter]停下来,因为他自己也被逗笑了[laughter]。', prompt_speech_16k, stream=False)):
|
for i, j in enumerate(cosyvoice.inference_cross_lingual('在他讲述那个荒诞故事的过程中,他突然[laughter]停下来,因为他自己也被逗笑了[laughter]。', prompt_speech_16k, stream=False)):
|
||||||
torchaudio.save('fine_grained_control_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate)
|
torchaudio.save('fine_grained_control_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate)
|
||||||
@@ -164,7 +167,7 @@ print(cosyvoice.list_available_spks())
|
|||||||
for i, j in enumerate(cosyvoice.inference_sft('你好,我是通义生成式语音大模型,请问有什么可以帮您的吗?', '中文女', stream=False)):
|
for i, j in enumerate(cosyvoice.inference_sft('你好,我是通义生成式语音大模型,请问有什么可以帮您的吗?', '中文女', stream=False)):
|
||||||
torchaudio.save('sft_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate)
|
torchaudio.save('sft_{}.wav'.format(i), j['tts_speech'], cosyvoice.sample_rate)
|
||||||
|
|
||||||
cosyvoice = CosyVoice('pretrained_models/CosyVoice-300M') # or change to pretrained_models/CosyVoice-300M-25Hz for 25Hz inference
|
cosyvoice = CosyVoice('pretrained_models/CosyVoice-300M')
|
||||||
# zero_shot usage, <|zh|><|en|><|jp|><|yue|><|ko|> for Chinese/English/Japanese/Cantonese/Korean
|
# zero_shot usage, <|zh|><|en|><|jp|><|yue|><|ko|> for Chinese/English/Japanese/Cantonese/Korean
|
||||||
prompt_speech_16k = load_wav('./asset/zero_shot_prompt.wav', 16000)
|
prompt_speech_16k = load_wav('./asset/zero_shot_prompt.wav', 16000)
|
||||||
for i, j in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '希望你以后能够做的比我还好呦。', prompt_speech_16k, stream=False)):
|
for i, j in enumerate(cosyvoice.inference_zero_shot('收到好友从远方寄来的生日礼物,那份意外的惊喜与深深的祝福让我心中充满了甜蜜的快乐,笑容如花儿般绽放。', '希望你以后能够做的比我还好呦。', prompt_speech_16k, stream=False)):
|
||||||
|
|||||||
@@ -66,6 +66,14 @@ class CosyVoice:
|
|||||||
spks = list(self.frontend.spk2info.keys())
|
spks = list(self.frontend.spk2info.keys())
|
||||||
return spks
|
return spks
|
||||||
|
|
||||||
|
def add_zero_shot_spk(self, prompt_text, prompt_speech_16k, zero_shot_spk_id):
|
||||||
|
assert zero_shot_spk_id != '', 'do not use empty zero_shot_spk_id'
|
||||||
|
model_input = self.frontend.frontend_zero_shot('', prompt_text, prompt_speech_16k, self.sample_rate, '')
|
||||||
|
del model_input['text']
|
||||||
|
del model_input['text_len']
|
||||||
|
self.frontend.spk2info[zero_shot_spk_id] = model_input
|
||||||
|
return True
|
||||||
|
|
||||||
def inference_sft(self, tts_text, spk_id, stream=False, speed=1.0, text_frontend=True):
|
def inference_sft(self, tts_text, spk_id, stream=False, speed=1.0, text_frontend=True):
|
||||||
for i in tqdm(self.frontend.text_normalize(tts_text, split=True, text_frontend=text_frontend)):
|
for i in tqdm(self.frontend.text_normalize(tts_text, split=True, text_frontend=text_frontend)):
|
||||||
model_input = self.frontend.frontend_sft(i, spk_id)
|
model_input = self.frontend.frontend_sft(i, spk_id)
|
||||||
@@ -77,12 +85,12 @@ class CosyVoice:
|
|||||||
yield model_output
|
yield model_output
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
|
||||||
def inference_zero_shot(self, tts_text, prompt_text, prompt_speech_16k, stream=False, speed=1.0, text_frontend=True):
|
def inference_zero_shot(self, tts_text, prompt_text, prompt_speech_16k, zero_shot_spk_id='', stream=False, speed=1.0, text_frontend=True):
|
||||||
prompt_text = self.frontend.text_normalize(prompt_text, split=False, text_frontend=text_frontend)
|
prompt_text = self.frontend.text_normalize(prompt_text, split=False, text_frontend=text_frontend)
|
||||||
for i in tqdm(self.frontend.text_normalize(tts_text, split=True, text_frontend=text_frontend)):
|
for i in tqdm(self.frontend.text_normalize(tts_text, split=True, text_frontend=text_frontend)):
|
||||||
if (not isinstance(i, Generator)) and len(i) < 0.5 * len(prompt_text):
|
if (not isinstance(i, Generator)) and len(i) < 0.5 * len(prompt_text):
|
||||||
logging.warning('synthesis text {} too short than prompt text {}, this may lead to bad performance'.format(i, prompt_text))
|
logging.warning('synthesis text {} too short than prompt text {}, this may lead to bad performance'.format(i, prompt_text))
|
||||||
model_input = self.frontend.frontend_zero_shot(i, prompt_text, prompt_speech_16k, self.sample_rate)
|
model_input = self.frontend.frontend_zero_shot(i, prompt_text, prompt_speech_16k, self.sample_rate, zero_shot_spk_id)
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
logging.info('synthesis text {}'.format(i))
|
logging.info('synthesis text {}'.format(i))
|
||||||
for model_output in self.model.tts(**model_input, stream=stream, speed=speed):
|
for model_output in self.model.tts(**model_input, stream=stream, speed=speed):
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ class CosyVoiceFrontEnd:
|
|||||||
if isinstance(text, Generator):
|
if isinstance(text, Generator):
|
||||||
logging.info('get tts_text generator, will skip text_normalize!')
|
logging.info('get tts_text generator, will skip text_normalize!')
|
||||||
return [text]
|
return [text]
|
||||||
if text_frontend is False:
|
if text_frontend is False or text == '':
|
||||||
return [text] if split is True else text
|
return [text] if split is True else text
|
||||||
text = text.strip()
|
text = text.strip()
|
||||||
if self.use_ttsfrd:
|
if self.use_ttsfrd:
|
||||||
@@ -154,24 +154,28 @@ class CosyVoiceFrontEnd:
|
|||||||
model_input = {'text': tts_text_token, 'text_len': tts_text_token_len, 'llm_embedding': embedding, 'flow_embedding': embedding}
|
model_input = {'text': tts_text_token, 'text_len': tts_text_token_len, 'llm_embedding': embedding, 'flow_embedding': embedding}
|
||||||
return model_input
|
return model_input
|
||||||
|
|
||||||
def frontend_zero_shot(self, tts_text, prompt_text, prompt_speech_16k, resample_rate):
|
def frontend_zero_shot(self, tts_text, prompt_text, prompt_speech_16k, resample_rate, zero_shot_spk_id):
|
||||||
tts_text_token, tts_text_token_len = self._extract_text_token(tts_text)
|
tts_text_token, tts_text_token_len = self._extract_text_token(tts_text)
|
||||||
prompt_text_token, prompt_text_token_len = self._extract_text_token(prompt_text)
|
if zero_shot_spk_id == '':
|
||||||
prompt_speech_resample = torchaudio.transforms.Resample(orig_freq=16000, new_freq=resample_rate)(prompt_speech_16k)
|
prompt_text_token, prompt_text_token_len = self._extract_text_token(prompt_text)
|
||||||
speech_feat, speech_feat_len = self._extract_speech_feat(prompt_speech_resample)
|
prompt_speech_resample = torchaudio.transforms.Resample(orig_freq=16000, new_freq=resample_rate)(prompt_speech_16k)
|
||||||
speech_token, speech_token_len = self._extract_speech_token(prompt_speech_16k)
|
speech_feat, speech_feat_len = self._extract_speech_feat(prompt_speech_resample)
|
||||||
if resample_rate == 24000:
|
speech_token, speech_token_len = self._extract_speech_token(prompt_speech_16k)
|
||||||
# cosyvoice2, force speech_feat % speech_token = 2
|
if resample_rate == 24000:
|
||||||
token_len = min(int(speech_feat.shape[1] / 2), speech_token.shape[1])
|
# cosyvoice2, force speech_feat % speech_token = 2
|
||||||
speech_feat, speech_feat_len[:] = speech_feat[:, :2 * token_len], 2 * token_len
|
token_len = min(int(speech_feat.shape[1] / 2), speech_token.shape[1])
|
||||||
speech_token, speech_token_len[:] = speech_token[:, :token_len], token_len
|
speech_feat, speech_feat_len[:] = speech_feat[:, :2 * token_len], 2 * token_len
|
||||||
embedding = self._extract_spk_embedding(prompt_speech_16k)
|
speech_token, speech_token_len[:] = speech_token[:, :token_len], token_len
|
||||||
model_input = {'text': tts_text_token, 'text_len': tts_text_token_len,
|
embedding = self._extract_spk_embedding(prompt_speech_16k)
|
||||||
'prompt_text': prompt_text_token, 'prompt_text_len': prompt_text_token_len,
|
model_input = {'prompt_text': prompt_text_token, 'prompt_text_len': prompt_text_token_len,
|
||||||
'llm_prompt_speech_token': speech_token, 'llm_prompt_speech_token_len': speech_token_len,
|
'llm_prompt_speech_token': speech_token, 'llm_prompt_speech_token_len': speech_token_len,
|
||||||
'flow_prompt_speech_token': speech_token, 'flow_prompt_speech_token_len': speech_token_len,
|
'flow_prompt_speech_token': speech_token, 'flow_prompt_speech_token_len': speech_token_len,
|
||||||
'prompt_speech_feat': speech_feat, 'prompt_speech_feat_len': speech_feat_len,
|
'prompt_speech_feat': speech_feat, 'prompt_speech_feat_len': speech_feat_len,
|
||||||
'llm_embedding': embedding, 'flow_embedding': embedding}
|
'llm_embedding': embedding, 'flow_embedding': embedding}
|
||||||
|
else:
|
||||||
|
model_input = self.spk2info[zero_shot_spk_id]
|
||||||
|
model_input['text'] = tts_text_token
|
||||||
|
model_input['text_len'] = tts_text_token_len
|
||||||
return model_input
|
return model_input
|
||||||
|
|
||||||
def frontend_cross_lingual(self, tts_text, prompt_speech_16k, resample_rate):
|
def frontend_cross_lingual(self, tts_text, prompt_speech_16k, resample_rate):
|
||||||
|
|||||||
Reference in New Issue
Block a user