porcupine_demo_mic.py
Go to the documentation of this file.
1 #
2 # Copyright 2018-2021 Picovoice Inc.
3 #
4 # You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE"
5 # file accompanying this source.
6 #
7 # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
8 # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 # specific language governing permissions and limitations under the License.
10 #
11 
12 import argparse
13 import os
14 import struct
15 import wave
16 from datetime import datetime
17 from threading import Thread
18 
19 import pvporcupine
20 from pvrecorder import PvRecorder
21 
22 
23 class PorcupineDemo(Thread):
24  """
25  Microphone Demo for Porcupine wake word engine. It creates an input audio stream from a microphone, monitors it, and
26  upon detecting the specified wake word(s) prints the detection time and wake word on console. It optionally saves
27  the recorded audio into a file for further debugging.
28  """
29 
30  def __init__(
31  self,
32  access_key,
33  library_path,
34  model_path,
35  keyword_paths,
36  sensitivities,
37  input_device_index=None,
38  output_path=None):
39 
40  """
41  Constructor.
42 
43  :param library_path: Absolute path to Porcupine's dynamic library.
44  :param model_path: Absolute path to the file containing model parameters.
45  :param keyword_paths: Absolute paths to keyword model files.
46  :param sensitivities: Sensitivities for detecting keywords. Each value should be a number within [0, 1]. A
47  higher sensitivity results in fewer misses at the cost of increasing the false alarm rate. If not set 0.5 will
48  be used.
49  :param input_device_index: Optional argument. If provided, audio is recorded from this input device. Otherwise,
50  the default audio input device is used.
51  :param output_path: If provided recorded audio will be stored in this location at the end of the run.
52  """
53 
54  super(PorcupineDemo, self).__init__()
55 
56  self._access_key = access_key
57  self._library_path = library_path
58  self._model_path = model_path
59  self._keyword_paths = keyword_paths
60  self._sensitivities = sensitivities
61  self._input_device_index = input_device_index
62 
63  self._output_path = output_path
64 
65  def run(self):
66  """
67  Creates an input audio stream, instantiates an instance of Porcupine object, and monitors the audio stream for
68  occurrences of the wake word(s). It prints the time of detection for each occurrence and the wake word.
69  """
70 
71  keywords = list()
72  for x in self._keyword_paths:
73  keyword_phrase_part = os.path.basename(x).replace('.ppn', '').split('_')
74  if len(keyword_phrase_part) > 6:
75  keywords.append(' '.join(keyword_phrase_part[0:-6]))
76  else:
77  keywords.append(keyword_phrase_part[0])
78 
79  porcupine = None
80  recorder = None
81  wav_file = None
82  try:
83  porcupine = pvporcupine.create(
84  access_key=self._access_key,
85  library_path=self._library_path,
86  model_path=self._model_path,
87  keyword_paths=self._keyword_paths,
88  sensitivities=self._sensitivities)
89 
90  recorder = PvRecorder(device_index=self._input_device_index, frame_length=porcupine.frame_length)
91  recorder.start()
92 
93  if self._output_path is not None:
94  wav_file = wave.open(self._output_path, "w")
95  wav_file.setparams((1, 2, 16000, 512, "NONE", "NONE"))
96 
97  print(f'Using device: {recorder.selected_device}')
98 
99  print('Listening {')
100  for keyword, sensitivity in zip(keywords, self._sensitivities):
101  print(' %s (%.2f)' % (keyword, sensitivity))
102  print('}')
103 
104  while True:
105  pcm = recorder.read()
106 
107  if wav_file is not None:
108  wav_file.writeframes(struct.pack("h" * len(pcm), *pcm))
109 
110  result = porcupine.process(pcm)
111  if result >= 0:
112  print('[%s] Detected %s' % (str(datetime.now()), keywords[result]))
113  except pvporcupine.PorcupineInvalidArgumentError as e:
114  print("One or more arguments provided to Porcupine is invalid: {\n" +
115  f"\t{self._access_key=}\n" +
116  f"\t{self._library_path=}\n" +
117  f"\t{self._model_path=}\n" +
118  f"\t{self._keyword_paths=}\n" +
119  f"\t{self._sensitivities=}\n" +
120  "}")
121  print(f"If all other arguments seem valid, ensure that '{self._access_key}' is a valid AccessKey")
122  raise e
123  except pvporcupine.PorcupineActivationError as e:
124  print("AccessKey activation error")
125  raise e
126  except pvporcupine.PorcupineActivationLimitError as e:
127  print(f"AccessKey '{self._access_key}' has reached it's temporary device limit")
128  raise e
129  except pvporcupine.PorcupineActivationRefusedError as e:
130  print(f"AccessKey '{self._access_key}' refused")
131  raise e
132  except pvporcupine.PorcupineActivationThrottledError as e:
133  print(f"AccessKey '{self._access_key}' has been throttled")
134  raise e
135  except pvporcupine.PorcupineError as e:
136  print(f"Failed to initialize Porcupine")
137  raise e
138  except KeyboardInterrupt:
139  print('Stopping ...')
140  finally:
141  if porcupine is not None:
142  porcupine.delete()
143 
144  if recorder is not None:
145  recorder.delete()
146 
147  if wav_file is not None:
148  wav_file.close()
149 
150  @classmethod
152  devices = PvRecorder.get_audio_devices()
153 
154  for i in range(len(devices)):
155  print(f'index: {i}, device name: {devices[i]}')
156 
157 
158 def main():
159  parser = argparse.ArgumentParser()
160 
161  parser.add_argument('--access_key',
162  help='AccessKey obtained from Picovoice Console (https://picovoice.ai/console/)')
163 
164  parser.add_argument(
165  '--keywords',
166  nargs='+',
167  help='List of default keywords for detection. Available keywords: %s' % ', '.join(sorted(pvporcupine.KEYWORDS)),
168  choices=sorted(pvporcupine.KEYWORDS),
169  metavar='')
170 
171  parser.add_argument(
172  '--keyword_paths',
173  nargs='+',
174  help="Absolute paths to keyword model files. If not set it will be populated from `--keywords` argument")
175 
176  parser.add_argument('--library_path', help='Absolute path to dynamic library.', default=pvporcupine.LIBRARY_PATH)
177 
178  parser.add_argument(
179  '--model_path',
180  help='Absolute path to the file containing model parameters.',
181  default=pvporcupine.MODEL_PATH)
182 
183  parser.add_argument(
184  '--sensitivities',
185  nargs='+',
186  help="Sensitivities for detecting keywords. Each value should be a number within [0, 1]. A higher " +
187  "sensitivity results in fewer misses at the cost of increasing the false alarm rate. If not set 0.5 " +
188  "will be used.",
189  type=float,
190  default=None)
191 
192  parser.add_argument('--audio_device_index', help='Index of input audio device.', type=int, default=-1)
193 
194  parser.add_argument('--output_path', help='Absolute path to recorded audio for debugging.', default=None)
195 
196  parser.add_argument('--show_audio_devices', action='store_true')
197 
198  args = parser.parse_args()
199 
200  if args.show_audio_devices:
201  PorcupineDemo.show_audio_devices()
202  else:
203  if args.access_key is None:
204  raise ValueError("AccessKey (--access_key) is required")
205  if args.keyword_paths is None:
206  if args.keywords is None:
207  raise ValueError("Either `--keywords` or `--keyword_paths` must be set.")
208 
209  keyword_paths = [pvporcupine.KEYWORD_PATHS[x] for x in args.keywords]
210  else:
211  keyword_paths = args.keyword_paths
212 
213  if args.sensitivities is None:
214  args.sensitivities = [0.5] * len(keyword_paths)
215 
216  if len(keyword_paths) != len(args.sensitivities):
217  raise ValueError('Number of keywords does not match the number of sensitivities.')
218 
220  access_key=args.access_key,
221  library_path=args.library_path,
222  model_path=args.model_path,
223  keyword_paths=keyword_paths,
224  sensitivities=args.sensitivities,
225  output_path=args.output_path,
226  input_device_index=args.audio_device_index).run()
227 
228 
229 if __name__ == '__main__':
230  main()
porcupine_demo_mic.PorcupineDemo
Definition: porcupine_demo_mic.py:23
porcupine_demo_mic.PorcupineDemo._model_path
_model_path
Definition: porcupine_demo_mic.py:50
porcupine_demo_mic.PorcupineDemo._output_path
_output_path
Definition: porcupine_demo_mic.py:55
porcupine_demo_mic.PorcupineDemo.__init__
def __init__(self, access_key, library_path, model_path, keyword_paths, sensitivities, input_device_index=None, output_path=None)
Definition: porcupine_demo_mic.py:30
porcupine_demo_mic.PorcupineDemo._sensitivities
_sensitivities
Definition: porcupine_demo_mic.py:52
porcupine_demo_mic.PorcupineDemo._keyword_paths
_keyword_paths
Definition: porcupine_demo_mic.py:51
porcupine_demo_mic.PorcupineDemo._access_key
_access_key
Definition: porcupine_demo_mic.py:48
porcupine_demo_mic.PorcupineDemo._library_path
_library_path
Definition: porcupine_demo_mic.py:49
porcupine_demo_mic.PorcupineDemo.show_audio_devices
def show_audio_devices(cls)
Definition: porcupine_demo_mic.py:151
porcupine_demo_mic.main
def main()
Definition: porcupine_demo_mic.py:158
porcupine_demo_mic.PorcupineDemo.run
def run(self)
Definition: porcupine_demo_mic.py:65
porcupine_demo_mic.PorcupineDemo._input_device_index
_input_device_index
Definition: porcupine_demo_mic.py:53
main
Definition: main.py:1


picovoice_driver
Author(s):
autogenerated on Fri Apr 1 2022 02:14:50