-
-
Save MatthewScholefield/f9a242078c771017b32a50f59c1eaabb to your computer and use it in GitHub Desktop.
Record wake words for Mycroft Precise
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# Copyright 2018 Mycroft AI Inc. | |
# | |
# Licensed under the Apache License, Version 2.0 (the "License"); | |
# you may not use this file except in compliance with the License. | |
# You may obtain a copy of the License at | |
# | |
# http://www.apache.org/licenses/LICENSE-2.0 | |
# | |
# Unless required by applicable law or agreed to in writing, software | |
# distributed under the License is distributed on an "AS IS" BASIS, | |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
# See the License for the specific language governing permissions and | |
# limitations under the License. | |
import tty | |
import wave | |
from os.path import isfile | |
from select import select | |
from sys import stdin | |
from termios import tcsetattr, tcgetattr, TCSADRAIN | |
from prettyparse import create_parser | |
import pyaudio | |
usage = ''' | |
Record audio samples for use with precise | |
:-w --width int 2 | |
Sample width of audio | |
:-r --rate int 16000 | |
Sample rate of audio | |
:-c --channels int 1 | |
Number of audio channels | |
''' | |
def key_pressed(): | |
return select([stdin], [], [], 0) == ([stdin], [], []) | |
def termios_wrapper(main): | |
global orig_settings | |
orig_settings = tcgetattr(stdin) | |
try: | |
hide_input() | |
main() | |
finally: | |
tcsetattr(stdin, TCSADRAIN, orig_settings) | |
def show_input(): | |
tcsetattr(stdin, TCSADRAIN, orig_settings) | |
def hide_input(): | |
tty.setcbreak(stdin.fileno()) | |
orig_settings = None | |
RECORD_KEY = ' ' | |
EXIT_KEY_CODE = 27 | |
def record_until(p, should_return, args): | |
chunk_size = 1024 | |
stream = p.open(format=p.get_format_from_width(args.width), channels=args.channels, rate=args.rate, | |
input=True, frames_per_buffer=chunk_size) | |
frames = [] | |
while not should_return(): | |
frames.append(stream.read(chunk_size)) | |
stream.stop_stream() | |
stream.close() | |
return b''.join(frames) | |
def save_audio(name, data, args): | |
wf = wave.open(name, 'wb') | |
wf.setnchannels(args.channels) | |
wf.setsampwidth(args.width) | |
wf.setframerate(args.rate) | |
wf.writeframes(data) | |
wf.close() | |
def next_name(name): | |
name += '.wav' | |
pos, num_digits = None, None | |
try: | |
pos = name.index('#') | |
num_digits = name.count('#') | |
except ValueError: | |
print("Name must contain at least one # to indicate where to put the number.") | |
raise | |
def get_name(i): | |
nonlocal name, pos | |
return name[:pos] + str(i).zfill(num_digits) + name[pos + num_digits:] | |
i = 0 | |
while True: | |
if not isfile(get_name(i)): | |
break | |
i += 1 | |
return get_name(i) | |
def wait_to_continue(): | |
while True: | |
c = stdin.read(1) | |
if c == RECORD_KEY: | |
return True | |
elif ord(c) == EXIT_KEY_CODE: | |
return False | |
def record_until_key(p, args): | |
def should_return(): | |
return key_pressed() and stdin.read(1) == RECORD_KEY | |
return record_until(p, should_return, args) | |
def _main(): | |
parser = create_parser(usage) | |
parser.add_argument('file_label', nargs='?', help='File label (Ex. recording-##)') | |
args = parser.parse_args() | |
show_input() | |
args.file_label = args.file_label or input("File label (Ex. recording-##): ") | |
args.file_label = args.file_label + ('' if '#' in args.file_label else '-##') | |
hide_input() | |
p = pyaudio.PyAudio() | |
while True: | |
print('Press space to record (esc to exit)...') | |
if not wait_to_continue(): | |
break | |
print('Recording...') | |
d = record_until_key(p, args) | |
name = next_name(args.file_label) | |
save_audio(name, d, args) | |
print('Saved as ' + name) | |
p.terminate() | |
def main(): | |
termios_wrapper(_main) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
prettyparse | |
pyaudio |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment