From cb5d25858682086ac211adfe156a4200866fe61c Mon Sep 17 00:00:00 2001
From: 志浩 <neo.dzh@alibaba-inc.com>
Date: 星期四, 23 二月 2023 21:53:20 +0800
Subject: [PATCH] sond pipeline
---
egs/mars/sd/scripts/real_meeting_process/remove_silence_from_wav.py | 0
egs/mars/sd/scripts/real_meeting_process/clip_meeting_without_silence.py | 53 +++++++++++++
egs/mars/sd/scripts/real_meeting_process/convert_rttm_to_seg_file.py | 0
egs/mars/sd/scripts/real_meeting_process/extract_nonoverlap_segments.py | 0
egs/mars/sd/scripts/real_meeting_process/calc_real_meeting_labels.py | 0
egs/mars/sd/scripts/real_meeting_process/dump_real_meeting_chunks.py | 137 ++++++++++++++++++++++++++++++++++
6 files changed, 190 insertions(+), 0 deletions(-)
diff --git a/egs/mars/sd/scripts/calc_real_meeting_labels.py b/egs/mars/sd/scripts/real_meeting_process/calc_real_meeting_labels.py
similarity index 100%
rename from egs/mars/sd/scripts/calc_real_meeting_labels.py
rename to egs/mars/sd/scripts/real_meeting_process/calc_real_meeting_labels.py
diff --git a/egs/mars/sd/scripts/real_meeting_process/clip_meeting_without_silence.py b/egs/mars/sd/scripts/real_meeting_process/clip_meeting_without_silence.py
new file mode 100644
index 0000000..11bc395
--- /dev/null
+++ b/egs/mars/sd/scripts/real_meeting_process/clip_meeting_without_silence.py
@@ -0,0 +1,53 @@
+import numpy as np
+from funasr.utils.job_runner import MultiProcessRunnerV3
+from funasr.utils.misc import load_scp_as_list, load_scp_as_dict
+import os
+import librosa
+import soundfile as sf
+from tqdm import tqdm
+import argparse
+
+
+class MyRunner(MultiProcessRunnerV3):
+
+ def prepare(self, parser):
+ parser.add_argument("wav_scp", type=str)
+ parser.add_argument("out_dir", type=str)
+ parser.add_argument("--chunk_dur", type=float, default=16)
+ parser.add_argument("--shift_dur", type=float, default=4)
+ args = parser.parse_args()
+
+ if not os.path.exists(args.out_dir):
+ os.makedirs(args.out_dir)
+
+ wav_scp = load_scp_as_list(args.wav_scp)
+ return wav_scp, None, args
+
+ def post(self, results_list, args):
+ pass
+
+
+def process(task_args):
+ _, task_list, _, args = task_args
+ chunk_len, shift_len = int(args.chunk_dur * args.sr), int(args.shift_dur * args.sr)
+ for mid, wav_path in tqdm(task_list, total=len(task_list), ascii=True, disable=args.no_pbar):
+ if not os.path.exists(os.path.join(args.out_dir, mid)):
+ os.makedirs(os.path.join(args.out_dir, mid))
+
+ wav = librosa.load(wav_path, args.sr, True)[0] * 32767
+ n_chunk = (len(wav) - chunk_len) // shift_len + 1
+ if (len(wav) - chunk_len) % shift_len > 0:
+ n_chunk += 1
+ for i in range(n_chunk):
+ seg = wav[i*shift_len: i*shift_len + chunk_len]
+ st = int(float(i*shift_len)/args.sr * 100)
+ dur = int(float(len(seg))/args.sr * 100)
+ file_name = "{}_S{:04d}_{:07d}_{:07d}.wav".format(mid, i, st, st+dur)
+ save_path = os.path.join(args.out_dir, mid, file_name)
+ sf.write(save_path, seg.astype(np.int16), args.sr, "PCM_16", "LITTLE", "WAV", True)
+ return None
+
+
+if __name__ == '__main__':
+ my_runner = MyRunner(process)
+ my_runner.run()
diff --git a/egs/mars/sd/scripts/convert_rttm_to_seg_file.py b/egs/mars/sd/scripts/real_meeting_process/convert_rttm_to_seg_file.py
similarity index 100%
rename from egs/mars/sd/scripts/convert_rttm_to_seg_file.py
rename to egs/mars/sd/scripts/real_meeting_process/convert_rttm_to_seg_file.py
diff --git a/egs/mars/sd/scripts/real_meeting_process/dump_real_meeting_chunks.py b/egs/mars/sd/scripts/real_meeting_process/dump_real_meeting_chunks.py
new file mode 100644
index 0000000..762d4c1
--- /dev/null
+++ b/egs/mars/sd/scripts/real_meeting_process/dump_real_meeting_chunks.py
@@ -0,0 +1,137 @@
+import soundfile
+import kaldiio
+from tqdm import tqdm
+import json
+import os
+from funasr.utils.misc import load_scp_as_list, load_scp_as_dict
+import numpy as np
+import argparse
+import random
+
+short_spk_list = []
+def calc_rand_ivc(spk, spk2utt, utt2ivc, utt2frames, total_len=3000):
+ all_utts = spk2utt[spk]
+ idx_list = list(range(len(all_utts)))
+ random.shuffle(idx_list)
+ count = 0
+ utt_list = []
+ for i in idx_list:
+ utt_id = all_utts[i]
+ utt_list.append(utt_id)
+ count += int(utt2frames[utt_id])
+ if count >= total_len:
+ break
+ if count < 300 and spk not in short_spk_list:
+ print("Speaker {} has only {} frames, but expect {} frames at least, use them all.".format(spk, count, 300))
+ short_spk_list.append(spk)
+
+ ivc_list = [kaldiio.load_mat(utt2ivc[utt])[np.newaxis, :] for utt in utt_list]
+ ivc = np.concatenate(ivc_list, axis=0)
+ ivc = np.mean(ivc, axis=0, keepdims=False)
+ return ivc
+
+
+def process(meeting_scp, labels_scp, spk2utt, utt2xvec, utt2frames, meeting2spk_list, args):
+ out_prefix = args.out
+
+ ivc_dim = 512
+ win_len, win_shift = 400, 160
+ label_weights = 2 ** np.array(list(range(args.n_spk)))
+ wav_writer = kaldiio.WriteHelper("ark,scp:{}_wav.ark,{}_wav.scp".format(out_prefix, out_prefix))
+ ivc_writer = kaldiio.WriteHelper("ark,scp:{}_profile.ark,{}_profile.scp".format(out_prefix, out_prefix))
+ label_writer = kaldiio.WriteHelper("ark,scp:{}_label.ark,{}_label.scp".format(out_prefix, out_prefix))
+
+
+ frames_list = []
+ chunk_size = int(args.chunk_size * args.sr)
+ chunk_shift = int(args.chunk_shift * args.sr)
+ for mid, meeting_wav_path in tqdm(meeting_scp, total=len(meeting_scp), ascii=True, disable=args.no_pbar):
+ meeting_wav, sr = soundfile.read(meeting_wav_path, dtype='float32')
+ num_chunk = (len(meeting_wav) - chunk_size) // chunk_shift + 1
+ meeting_labels = np.load(labels_scp[mid])
+ for i in range(num_chunk):
+ st, ed = i*chunk_shift, i*chunk_shift+chunk_size
+ seg_id = "{}-{:03d}-{:06d}-{:06d}".format(mid, i, int(st/args.sr*100), int(ed/args.sr*100))
+ wav_writer(seg_id, meeting_wav[st: ed])
+
+ xvec_list = []
+ for spk in meeting2spk_list[mid]:
+ spk_xvec = calc_rand_ivc(spk, spk2utt, utt2xvec, utt2frames, 1000)[np.newaxis, :]
+ xvec_list.append(spk_xvec)
+ for _ in range(args.n_spk - len(xvec_list)):
+ xvec_list.append(np.zeros((ivc_dim,), dtype=np.float32))
+ xvec = np.row_stack(xvec_list)
+ ivc_writer(seg_id, xvec)
+
+ wav_label = meeting_labels[st:ed, :]
+ frame_num = (ed-st) // win_shift
+ # wav_label = np.pad(wav_label, ((win_len/2, win_len/2), (0, 0)), "constant")
+ feat_label = np.zeros((frame_num, wav_label.shape[1]), dtype=int)
+ for i in range(frame_num):
+ frame_label = wav_label[i*win_shift: (i+1)*win_shift, :]
+ feat_label[i, :] = (np.sum(frame_label, axis=0) > 0).astype(int)
+ label_writer(seg_id, feat_label)
+
+ frames_list.append((mid, feat_label.shape[0]))
+ return frames_list
+
+
+def calc_spk_list(rttm_path):
+ spk_list = []
+ for one_line in open(rttm_path, "rt"):
+ parts = one_line.strip().split(" ")
+ mid, st, dur, spk = parts[1], float(parts[3]), float(parts[4]), int(parts[7])
+ spk = "{}_S{:03d}".format(mid, spk)
+ if spk not in spk_list:
+ spk_list.append(spk)
+
+ return spk_list
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--dir", required=True, type=str, default=None,
+ help="feats.scp")
+ parser.add_argument("--out", required=True, type=str, default=None,
+ help="The prefix of dumpped files.")
+ parser.add_argument("--n_spk", type=int, default=4)
+ parser.add_argument("--use_lfr", default=False, action="store_true")
+ parser.add_argument("--no_pbar", default=False, action="store_true")
+ parser.add_argument("--sr", type=int, default=16000)
+ parser.add_argument("--chunk_size", type=int, default=16)
+ parser.add_argument("--chunk_shift", type=int, default=4)
+ args = parser.parse_args()
+
+ if not os.path.exists(os.path.dirname(args.out)):
+ os.makedirs(os.path.dirname(args.out))
+
+ meetings_scp = load_scp_as_list(os.path.join(args.dir, "meetings_rmsil.scp"))
+ labels_scp = load_scp_as_dict(os.path.join(args.dir, "labels.scp"))
+ rttm_scp = load_scp_as_list(os.path.join(args.dir, "rttm.scp"))
+ utt2spk = load_scp_as_dict(os.path.join(args.dir, "utt2spk"))
+ utt2xvec = load_scp_as_dict(os.path.join(args.dir, "utt2xvec"))
+ utt2wav = load_scp_as_dict(os.path.join(args.dir, "wav.scp"))
+ utt2frames = {}
+ for uttid, wav_path in utt2wav.items():
+ wav, sr = soundfile.read(wav_path, dtype="int16")
+ utt2frames[uttid] = int(len(wav) / sr * 100)
+
+ meeting2spk_list = {}
+ for mid, rttm_path in rttm_scp:
+ meeting2spk_list[mid] = calc_spk_list(rttm_path)
+
+ spk2utt = {}
+ for utt, spk in utt2spk.items():
+ if utt in utt2xvec and utt in utt2frames and int(utt2frames[utt]) > 25:
+ if spk not in spk2utt:
+ spk2utt[spk] = []
+ spk2utt[spk].append(utt)
+
+ # random.shuffle(feat_scp)
+ meeting_lens = process(meetings_scp, labels_scp, spk2utt, utt2xvec, utt2frames, meeting2spk_list, args)
+ total_frames = sum([x[1] for x in meeting_lens])
+ print("Total chunks: {:6d}, total frames: {:10d}".format(len(meeting_lens), total_frames))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/egs/mars/sd/scripts/extract_nonoverlap_segments.py b/egs/mars/sd/scripts/real_meeting_process/extract_nonoverlap_segments.py
similarity index 100%
rename from egs/mars/sd/scripts/extract_nonoverlap_segments.py
rename to egs/mars/sd/scripts/real_meeting_process/extract_nonoverlap_segments.py
diff --git a/egs/mars/sd/scripts/remove_silence_from_wav.py b/egs/mars/sd/scripts/real_meeting_process/remove_silence_from_wav.py
similarity index 100%
rename from egs/mars/sd/scripts/remove_silence_from_wav.py
rename to egs/mars/sd/scripts/real_meeting_process/remove_silence_from_wav.py
--
Gitblit v1.9.1