inoryQwQ commited on
Commit
da6a2e1
·
verified ·
1 Parent(s): c61c22f

align with silero-vad-axera 0.1.2 (axmodel-only)

Browse files
Files changed (4) hide show
  1. README.md +15 -12
  2. StreamVAD.py +26 -20
  3. main.py +5 -5
  4. requirements.txt +5 -6
README.md CHANGED
@@ -6,22 +6,25 @@ license: mit
6
  流式语音端点识别
7
 
8
 
9
- ## 安装依赖
10
-
11
- ```
12
- sudo apt install libsndfile1
13
-
14
- pip install -r requirements.txt
15
- ```
 
 
16
 
17
  ## Demo
18
 
19
  ### CLI
20
 
21
- ```
22
- python main.py --input demo.wav --output_dir output --model silero_vad.onnx
23
- ```
24
- 被分段的语音后保存在output目录中
 
25
 
26
 
27
  ### Gradio
@@ -63,4 +66,4 @@ result的格式为:
63
  }
64
  ```
65
 
66
- 时间戳的格式可通过StreamVAD.datetime_format设置
 
6
  流式语音端点识别
7
 
8
 
9
+ ## 安装依赖
10
+
11
+ 本仓库只支持 **axmodel(NPU)推理**(AX650 / AX630C),不再支持 onnx CPU 后端。
12
+
13
+ ```
14
+ sudo apt install libsndfile1
15
+
16
+ pip install -r requirements.txt
17
+ ```
18
 
19
  ## Demo
20
 
21
  ### CLI
22
 
23
+ ```
24
+ python main.py --input demo.wav --backend ax650 --output_dir output # AX650 板
25
+ python main.py --input demo.wav --backend ax630c --output_dir output # AX620E/AX630C 板
26
+ ```
27
+ 被分段的语音后保存在output目录中
28
 
29
 
30
  ### Gradio
 
66
  }
67
  ```
68
 
69
+ 时间戳的格式可通过StreamVAD.datetime_format设置
StreamVAD.py CHANGED
@@ -3,7 +3,7 @@ import numpy as np
3
  from datetime import datetime, timedelta
4
 
5
 
6
- class StreamVAD:
7
  def __init__(self, backend='ax650',
8
  sensitivity=0.5,
9
  silence_ms=200,
@@ -17,10 +17,13 @@ class StreamVAD:
17
  datetime_format: format of datetime in return data
18
  '''
19
 
20
- self.model = load_silero_vad(backend)
21
- self.sensitivity = sensitivity
22
- self.silence_ms = silence_ms
23
- self.datetime_format = datetime_format
 
 
 
24
 
25
  self.reset()
26
 
@@ -37,19 +40,22 @@ class StreamVAD:
37
  self.model.reset_states()
38
 
39
 
40
- def run(self, audio: np.ndarray, sr: int = 16000):
41
- # record datetime
42
- cur_ts = datetime.now()
43
-
44
- # freq scale
45
- freq_scale = int(sr / self.model.sr)
46
-
47
- # inference
48
- speech_probs = self.model.audio_forward(audio, sr)[0]
49
-
50
- for i, prob in enumerate(speech_probs):
51
- audio_slice = audio[i * self.model.num_samples * freq_scale : (i + 1) * self.model.num_samples * freq_scale]
52
- ts = cur_ts.strftime(self.datetime_format)
 
 
 
53
 
54
  # is speech
55
  if prob > 1 - self.sensitivity:
@@ -66,7 +72,7 @@ class StreamVAD:
66
  self.silence_count += 1
67
 
68
  # exceed silence limit
69
- if 1000 * self.silence_count * self.model.num_samples / self.model.sr > self.silence_ms:
70
  # return audio segment
71
  self.return_data['end_ts'] = ts
72
  self.return_data['audio'] = np.concatenate(self.vad_data_list, axis=-1)
@@ -78,4 +84,4 @@ class StreamVAD:
78
  self.vad_data_list.append(audio_slice)
79
 
80
  # timestamp
81
- cur_ts += timedelta(seconds=self.model.num_samples / self.model.sr)
 
3
  from datetime import datetime, timedelta
4
 
5
 
6
+ class StreamVAD:
7
  def __init__(self, backend='ax650',
8
  sensitivity=0.5,
9
  silence_ms=200,
 
17
  datetime_format: format of datetime in return data
18
  '''
19
 
20
+ self.model = load_silero_vad(backend)
21
+ # axmodel 为 16k 静态图:采样率 16000、每帧 512 样本
22
+ self.sr = self.model.sample_rates[0]
23
+ self.num_samples = 512
24
+ self.sensitivity = sensitivity
25
+ self.silence_ms = silence_ms
26
+ self.datetime_format = datetime_format
27
 
28
  self.reset()
29
 
 
40
  self.model.reset_states()
41
 
42
 
43
+ def run(self, audio: np.ndarray, sr: int = 16000):
44
+ audio = np.asarray(audio, dtype=np.float32)
45
+ # record datetime
46
+ cur_ts = datetime.now()
47
+
48
+ # freq scale
49
+ freq_scale = int(sr / self.sr)
50
+
51
+ # inference
52
+ speech_probs = self.model.audio_forward(audio, sr)[0]
53
+
54
+ for i, prob in enumerate(speech_probs):
55
+ audio_slice = audio[i * self.num_samples * freq_scale : (i + 1) * self.num_samples * freq_scale]
56
+ if len(audio_slice) < self.num_samples * freq_scale:
57
+ audio_slice = np.pad(audio_slice, (0, self.num_samples * freq_scale - len(audio_slice)))
58
+ ts = cur_ts.strftime(self.datetime_format)
59
 
60
  # is speech
61
  if prob > 1 - self.sensitivity:
 
72
  self.silence_count += 1
73
 
74
  # exceed silence limit
75
+ if 1000 * self.silence_count * self.num_samples / self.sr > self.silence_ms:
76
  # return audio segment
77
  self.return_data['end_ts'] = ts
78
  self.return_data['audio'] = np.concatenate(self.vad_data_list, axis=-1)
 
84
  self.vad_data_list.append(audio_slice)
85
 
86
  # timestamp
87
+ cur_ts += timedelta(seconds=self.num_samples / self.sr)
main.py CHANGED
@@ -8,7 +8,7 @@ import soundfile as sf
8
  def get_args():
9
  parser = argparse.ArgumentParser()
10
  parser.add_argument('--input', type=str, required=True, help='Input audio file')
11
- parser.add_argument('--backend', type=str, default='ax650', choices=['ax650', 'ax630c', 'onnx'])
12
  parser.add_argument('--output_dir', type=str, default='output', help='Output audio dir')
13
  return parser.parse_args()
14
 
@@ -21,15 +21,15 @@ def main():
21
  sensitivity=0.5,
22
  silence_ms=200)
23
 
24
- audio, _ = librosa.load(args.input, sr=vad.model.sr, mono=True)
25
  i = 0
26
- for result in vad.run(audio, vad.model.sr):
27
  if result:
28
  print(result)
29
  filename = os.path.join(args.output_dir, f"{i}.wav")
30
- sf.write(filename, result['audio'], samplerate=vad.model.sr)
31
  i += 1
32
 
33
 
34
  if __name__ == '__main__':
35
- main()
 
8
  def get_args():
9
  parser = argparse.ArgumentParser()
10
  parser.add_argument('--input', type=str, required=True, help='Input audio file')
11
+ parser.add_argument('--backend', type=str, default='ax650', choices=['ax650', 'ax630c'])
12
  parser.add_argument('--output_dir', type=str, default='output', help='Output audio dir')
13
  return parser.parse_args()
14
 
 
21
  sensitivity=0.5,
22
  silence_ms=200)
23
 
24
+ audio, _ = librosa.load(args.input, sr=vad.sr, mono=True)
25
  i = 0
26
+ for result in vad.run(audio, vad.sr):
27
  if result:
28
  print(result)
29
  filename = os.path.join(args.output_dir, f"{i}.wav")
30
+ sf.write(filename, result['audio'], samplerate=vad.sr)
31
  i += 1
32
 
33
 
34
  if __name__ == '__main__':
35
+ main()
requirements.txt CHANGED
@@ -1,6 +1,5 @@
1
- onnxruntime>=1.16.1
2
- librosa==0.9.1
3
- numpy<2.0
4
- soundfile
5
- axengine @ https://github.com/AXERA-TECH/pyaxengine/releases/download/0.1.3.rc2/axengine-0.1.3-py3-none-any.whl
6
- silero_vad_axera
 
1
+ librosa==0.9.1
2
+ numpy<2.0
3
+ soundfile
4
+ axengine @ https://github.com/AXERA-TECH/pyaxengine/releases/download/0.1.3.rc2/axengine-0.1.3-py3-none-any.whl
5
+ silero-vad-axera>=0.1.2