-
Notifications
You must be signed in to change notification settings - Fork 109
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use fmedia for recording voice when not in Linux
Use thread instead of a non blocking stream which is specific to Linux
- Loading branch information
Papoteur
committed
Oct 24, 2021
1 parent
66a2c5b
commit 6916bbb
Showing
1 changed file
with
37 additions
and
22 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,6 +33,7 @@ import subprocess | |
import sys | ||
import tempfile | ||
import time | ||
from functools import partial | ||
|
||
# Types. | ||
from typing import ( | ||
|
@@ -98,12 +99,9 @@ def file_remove_if_exists(filepath: str) -> bool: | |
return False | ||
|
||
|
||
def file_handle_make_non_blocking(file_handle: IO[bytes]) -> None: | ||
import fcntl | ||
|
||
# Get current `file_handle` flags. | ||
flags = fcntl.fcntl(file_handle.fileno(), fcntl.F_GETFL) | ||
fcntl.fcntl(file_handle, fcntl.F_SETFL, flags | os.O_NONBLOCK) | ||
def enqueue_output(vosk_out, queue): | ||
for block in iter(partial(vosk_out.read, 16384), b""): | ||
queue.put(block) | ||
|
||
|
||
def execfile(filepath: str, mod: Optional[ModuleType] = None) -> Optional[ModuleType]: | ||
|
@@ -539,22 +537,38 @@ def text_from_vosk_pipe( | |
) | ||
sys.exit(1) | ||
|
||
cmd = ( | ||
"parec", | ||
"--record", | ||
"--rate=44100", | ||
"--channels=1", | ||
*(("--device=%s" % pulse_device_name,) if pulse_device_name else ()), | ||
"--format=s16ne", | ||
"--latency=10", | ||
) | ||
if os.name == "posix": | ||
cmd = ( | ||
"parec", | ||
"--record", | ||
"--rate=44100", | ||
"--channels=1", | ||
*(("--device=%s" % pulse_device_name,) if pulse_device_name else ()), | ||
"--format=s16ne", | ||
"--latency=10", | ||
) | ||
else: | ||
# https://stsaz.github.io/fmedia/recording/#stdout | ||
cmd = ( | ||
"fmedia", | ||
"--record", | ||
"[email protected]", | ||
"--rate=%d" % sample_rate, | ||
"--channels=mono", | ||
"--format=int16", | ||
"--notui", | ||
) | ||
ps = subprocess.Popen(cmd, stdout=subprocess.PIPE) | ||
|
||
stdout = ps.stdout | ||
assert stdout is not None | ||
|
||
# Needed so whatever is available can be read (without waiting). | ||
file_handle_make_non_blocking(stdout) | ||
from threading import Thread | ||
from queue import Queue, Empty | ||
|
||
vosk_queue:Queue = Queue() | ||
t = Thread(target=enqueue_output, args=(stdout, vosk_queue)) | ||
t.daemon = True | ||
t.start() | ||
|
||
# `mypy` doesn't know about VOSK. | ||
import vosk # type: ignore | ||
|
@@ -628,9 +642,11 @@ def text_from_vosk_pipe( | |
if code != -1: | ||
# Mostly the data read is quite small (under 1k). | ||
# Only the 1st entry in the loop reads a lot of data due to the time it takes to initialize the VOSK module. | ||
data = stdout.read(block_size) | ||
|
||
if data: | ||
try: | ||
data = vosk_queue.get_nowait() | ||
except Empty: | ||
pass | ||
else: | ||
ok = rec.AcceptWaveform(data) | ||
|
||
if ok: | ||
|
@@ -721,7 +737,6 @@ def main_begin( | |
if not vosk_model_dir: | ||
vosk_model_dir = calc_user_config_path("model") | ||
# If this still doesn't exist the error is handled later. | ||
|
||
# | ||
# Initialize the recording state and perform some sanity checks. | ||
# | ||
|