|
| 1 | +from warnings import warn |
| 2 | + |
| 3 | +import torch |
| 4 | + |
| 5 | +from nemo.collections.asr.models import SortformerEncLabelModel |
| 6 | +from nemo.collections.asr.parts.mixins.diarization import DiarizeConfig |
| 7 | + |
| 8 | + |
| 9 | +class SortformerDiarizer: |
| 10 | + def __init__(self, device): |
| 11 | + self.model: SortformerEncLabelModel = SortformerEncLabelModel.from_pretrained( |
| 12 | + "nvidia/diar_streaming_sortformer_4spk-v2", map_location=device |
| 13 | + ) |
| 14 | + |
| 15 | + self.model.sortformer_modules.chunk_len = 340 |
| 16 | + self.model.sortformer_modules.chunk_right_context = 40 |
| 17 | + self.model.sortformer_modules.fifo_len = 40 |
| 18 | + self.model.sortformer_modules.spkcache_update_period = 300 |
| 19 | + self.model.sortformer_modules.spkcache_len = 188 |
| 20 | + self.model.sortformer_modules._check_streaming_parameters() |
| 21 | + |
| 22 | + warn( |
| 23 | + "Sortformer supports maximum of 4 speakers only, " |
| 24 | + "please use MSDD if your audio has more than 4 speakers", |
| 25 | + Warning, |
| 26 | + ) |
| 27 | + |
| 28 | + self.model.eval() |
| 29 | + |
| 30 | + def diarize(self, audio: torch.Tensor): |
| 31 | + with torch.inference_mode(): |
| 32 | + processed_signal, processed_signal_length = self.model.process_signal( |
| 33 | + audio_signal=audio, |
| 34 | + audio_signal_length=torch.tensor([audio.shape[-1]]), |
| 35 | + ) |
| 36 | + processed_signal = processed_signal[:, :, : processed_signal_length.max()] |
| 37 | + |
| 38 | + preds = self.model.forward_streaming(processed_signal, processed_signal_length) |
| 39 | + preds = preds.cpu() |
| 40 | + |
| 41 | + # TODO: make this tunable |
| 42 | + diarize_cfg = DiarizeConfig( |
| 43 | + postprocessing_params={ |
| 44 | + "onset": 0.5, |
| 45 | + "offset": 0.5, |
| 46 | + "pad_onset": 0.0, |
| 47 | + "pad_offset": 0.0, |
| 48 | + "min_duration_on": 0.0, |
| 49 | + "min_duration_off": 0.0, |
| 50 | + } |
| 51 | + ) |
| 52 | + |
| 53 | + audio_rttm_map_dict = { |
| 54 | + "audio": { |
| 55 | + "uniq_id": "audio", |
| 56 | + "audio_filepath": "tensor_audio", |
| 57 | + "offset": 0.0, |
| 58 | + "duration": None, |
| 59 | + "text": "-", |
| 60 | + "label": "infer", |
| 61 | + } |
| 62 | + } |
| 63 | + |
| 64 | + self.model._diarize_audio_rttm_map = audio_rttm_map_dict |
| 65 | + uniq_ids = list(self.model._diarize_audio_rttm_map.keys()) |
| 66 | + processed_outputs = self.model._diarize_output_processing(preds, uniq_ids, diarize_cfg) |
| 67 | + self.model._diarize_audio_rttm_map = {} |
| 68 | + |
| 69 | + labels = [] |
| 70 | + for label in processed_outputs[0]: |
| 71 | + start, end, speaker = label.split() |
| 72 | + start, end = float(start), float(end) |
| 73 | + start, end = int(start * 1000), int(end * 1000) |
| 74 | + labels.append((start, end, int(speaker.split("_")[1]))) |
| 75 | + |
| 76 | + labels = sorted(labels, key=lambda x: x[0]) |
| 77 | + |
| 78 | + return labels |
0 commit comments