La separación de oradores, o registro de oradores, resuelve principalmente el problema de cuándo y qué dijo el orador. Escenarios de aplicación típicos: reuniones de varias personas, escenarios de agentes de ventas/servicio al cliente.
La implementación típica se basa en canalizaciones.
Primero, los clips de sonido se segmentan según MarbleNet de VAD (detección de actividad de voz), luego las características de los altavoces se extraen según TitaNet-L, luego los altavoces se distinguen mediante agrupación y, finalmente, las etiquetas de los altavoces se separan mediante redes neuronales.
1. Instalación del entorno Nemo
2. Dependencia de referencia
importar nemo.collections.asr como nemo_asr
importar numpy como np
desde IPython.display importar audio, mostrar
importar librosa
importar os
importar wget
importar matplotlib.pyplot como plt
importar nemo
importar glob
importar pprint
pp = pprint.PrettyPrinter(sangría=4)
3. Muestras aisladas localmente
ROOT = os.getcwd()
data_dir = os.path.join(ROOT,'data')
print(data_dir)
os.makedirs(data_dir, exist_ok=True)
AUDIO_FILENAME = os.path.join(data_dir,'prueba.wav')
audio_file_list = glob.glob(f"{data_dir}/test.wav")
print("Lista de archivos de audio de entrada: \n", audio_file_list)
señal, frecuencia_muestra = librosa.load(AUDIO_FILENAME, sr=16000)
print(velocidad_muestra)
visualización(Audio(señal,velocidad=velocidad_muestra))
3. Ajuste de la práctica de capacitación utilizando el modelo entrenado blog-CSDN blog-CSDN de NeMo chino/inglés ASR model_wxl781227
my_asr_model = nemo_asr.models.EncDecCTCModel.restore_from("my_stt_zh_quartznet15x5.nemo")
4. Defina la función de salida de forma de onda y la función de coloración de forma de onda.
def display_waveform(signal,text='Audio',overlay_color=[]):
fig,ax = plt.subplots(1,1)
fig.set_figwidth(20)
fig.set_figheight(2)
plt.scatter(np.arange(len (señal)),señal,s=1,marcador='o',c='k')
si len(overlay_color):
plt.scatter(np.arange(len(señal)),señal,s=1,marcador ='o',c=overlay_color)
fig.suptitle(texto, tamaño de fuente=16)
plt.xlabel('tiempo (segundos)', tamaño de fuente=18)
plt.ylabel('intensidad de la señal', tamaño de fuente=14);
plt.axis([0,len(señal),-0.5,+0.5])
time_axis,_ = plt.xticks();
plt.xticks(time_axis[:-1],time_axis[:-1]/sample_rate);
COLORS="bgcm y".split()
importar archivo de sonido
def get_color(signal,speech_labels,sample_rate=sample_rate):
c=np.array(['k']*len(signal))
para marca de tiempo en etiquetas de voz:
inicio, fin, etiqueta = marca de tiempo.split()
inicio, fin = int (float(start)*sample_rate),int(float(end)*sample_rate),
corp_wav = señal[start:end]
soundfile.write(f"/NeMo/tutorials/speaker_tasks/data/test_{start}_{end} _{label}.wav", corp_wav, sample_rate)
print(label,my_asr_model.transcribe([f"/NeMo/tutorials/speaker_tasks/data/test_{start}_{end}_{label}.wav"]))
if etiqueta == "voz":
código = 'rojo'
else:
código = COLORES[int(label.split('_')[-1])]
c[inicio:fin]=código
volver c
5. Genera la forma de onda antes de la separación.
display_waveform(señal)
6. Introduzca el archivo de configuración yaml original.
from omegaconf import OmegaConf
importshuthil
DOMAIN_TYPE = "meeting" # Puede ser de reunión o telefónico según el tipo de dominio del archivo de audio
CONFIG_FILE_NAME = f"diar_infer_{DOMAIN_TYPE}.yaml"
CONFIG_URL = f"https://raw.githubusercontent.com/NVIDIA/NeMo/main/examples/speaker_tasks/diarization/conf/inference/{CONFIG_FILE_NAME}"
si no os.path.exists(os.path.join(data_dir,CONFIG_FILE_NAME)):
CONFIG = wget.download(CONFIG_URL, data_dir)
más:
CONFIG = os.path.join(data_dir,CONFIG_FILE_NAME)
cfg = OmegaConf.load(CONFIG)
imprimir(OmegaConf.to_yaml(cfg))
7. Crear archivo principal
# Cree un archivo de manifiesto para la entrada con el siguiente formato.
# {"audio_filepath": "/ruta/al/audio_file", "offset": 0, "duration": null, "label": "infer", "text": "-", # "num_speakers": null
, "rttm_filepath": "/path/to/rttm/file", "uem_filepath"="/path/to/uem/filepath"} import json meta = { '
audio_filepath
' : AUDIO_FILENAME, 'offset': 0, 'duration' :Ninguno, 'etiqueta': 'inferir', 'texto': '-', 'num_speakers': Ninguno, 'rttm_filepath': Ninguno, 'uem_filepath':
cfg.diarizer.manifest_filepath = os.path.join(data_dir,'input_manifest.json')
!cat {cfg.diarizer.manifest_filepath}
8. Configure el modelo de canalización utilizado.
pretrained_speaker_model='titanet-l.nemo'
cfg.diarizer.manifest_filepath = cfg.diarizer.manifest_filepath
cfg.diarizer.out_dir = data_dir #Directorio para almacenar archivos intermedios y resultados de predicción
cfg.diarizer.speaker_embeddings.model_path = pretrained_speaker_model
cfg.diarizer.clustering .parameters.oracle_num_speakers=Ninguno
# Usando Neural VAD y Conformer ASR
cfg.diarizer.vad.model_path = 'vad_multilingual_marblenet'
cfg.diarizer.asr.model_path = 'my_stt_zh_quartznet15x5.nemo'
cfg.diarizer.oracle_vad = False # ----> No usando Oracle VAD
cfg. diarizer.asr.parameters.asr_based_vad = Falso
cfg.batch_size = 2
9. Ejecute ASR para obtener la marca de tiempo.
de nemo.collections.asr.parts.utils.decoder_timestamps_utils importar ASRDecoderTimeStamps
asr_decoder_ts = ASRDecoderTimeStamps(cfg.diarizer)
asr_model = asr_decoder_ts.set_asr_model()
word_hyp, word_ts_hyp = asr_decoder_ts.run_ASR(asr_model)
print("Diccionario de salida de palabras decodificadas: \n", word_hyp['test'])
print("Diccionario de marcas de tiempo a nivel de palabras: \n", word_ts_hyp['test'])
10. Cree un objeto de separación fuera de línea de ASR
de nemo.collections.asr.parts.utils.diarization_utils importar OfflineDiarWithASR
asr_diar_offline = OfflineDiarWithASR(cfg.diarizer)
asr_diar_offline.word_ts_anchor_offset = asr_decoder_ts.word_ts_anchor_offset
11. Realizar separación fuera de línea
diar_hyp, diar_score = asr_diar_offline.run_diarization(cfg, word_ts_hyp)
print("Salida de la hipótesis de diarización: \n", diar_hyp['test'])
12. Muestra los resultados de la separación fuera de línea.
def read_file(path_to_file):
con open(path_to_file) como f:
contenidos = f.read().splitlines()
devolver contenido
predicted_speaker_label_rttm_path = f"{data_dir}/pred_rttms/test.rttm"
pred_rttm = read_file(predicted_speaker_label_rttm_path)
pp.pprint(pred_rttm)
de nemo.collections.asr.parts.utils.speaker_utils importar rttm_to_labels
pred_labels = rttm_to_labels(predicted_speaker_label_rttm_path)
color = get_color(señal, pred_labels)
display_waveform(señal,'Audio con etiquetas de altavoz', color)
display(Audio(señal,velocidad=velocidad_muestra))
[ 'Prueba de ALTAVOZ2 1 0.000 4.125 <NA> <NA> altavoz_1 <NA> <NA>', 'Prueba de ALTAVOZ2 1 4.125 4.565 <NA> <NA> altavoz_0 <NA> <NA>']
Transcripción: 0%| | 0/1 [00:00<?, ?it/s]
altavoz_1 ['Oye, anteayer me dijiste cuál es la tasa de interés a 12 períodos']
Transcripción: 0%| | 0/1 [00:00<?, ?it/s]
altavoz_0 ['Si el número de trabajo es 908262, entonces será 0,810,000, luego se dividirá entre 120,000 y el interés será 80']