rustpotter detections optimization + few code improvements
This commit is contained in:
parent
88d73eeb10
commit
61b7a79455
12 changed files with 64 additions and 58 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -4846,7 +4846,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustpotter"
|
name = "rustpotter"
|
||||||
version = "3.0.2"
|
version = "3.0.2"
|
||||||
source = "git+https://github.com/Priler/rustpotter#5604a094b4a21ad12645e5aac5ffc463a2892af8"
|
source = "git+https://github.com/Priler/rustpotter#f0d5c4d6b63aa1ebb6e0e81089993e4ae7aef3d8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"candle-core",
|
"candle-core",
|
||||||
"candle-nn",
|
"candle-nn",
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ fn main() -> Result<(), String> {
|
||||||
|
|
||||||
// start the app (in the background thread)
|
// start the app (in the background thread)
|
||||||
std::thread::spawn(|| {
|
std::thread::spawn(|| {
|
||||||
app::start();
|
let _ = app::start();
|
||||||
});
|
});
|
||||||
|
|
||||||
tray::init_blocking();
|
tray::init_blocking();
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ use crate::{config, DB, SOUND_DIR};
|
||||||
static AUDIO_TYPE: OnceCell<AudioType> = OnceCell::new();
|
static AUDIO_TYPE: OnceCell<AudioType> = OnceCell::new();
|
||||||
|
|
||||||
pub fn init() -> Result<(), ()> {
|
pub fn init() -> Result<(), ()> {
|
||||||
if !AUDIO_TYPE.get().is_none() {
|
if AUDIO_TYPE.get().is_some() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} // already initialized
|
} // already initialized
|
||||||
|
|
||||||
|
|
@ -29,7 +29,7 @@ pub fn init() -> Result<(), ()> {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
info!("Successfully initialized Rodio audio backend.");
|
info!("Successfully initialized Rodio audio backend.");
|
||||||
}
|
}
|
||||||
Err(msg) => {
|
Err(()) => {
|
||||||
error!("Failed to initialize Rodio audio backend.");
|
error!("Failed to initialize Rodio audio backend.");
|
||||||
|
|
||||||
return Err(());
|
return Err(());
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ static STREAM_HANDLE: OnceCell<OutputStream> = OnceCell::new();
|
||||||
static SINK: OnceCell<Sink> = OnceCell::new();
|
static SINK: OnceCell<Sink> = OnceCell::new();
|
||||||
|
|
||||||
pub fn init() -> Result<(), ()> {
|
pub fn init() -> Result<(), ()> {
|
||||||
if !STREAM_HANDLE.get().is_none() {
|
if STREAM_HANDLE.get().is_some() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} // already initialized
|
} // already initialized
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,13 @@ pub fn parse_commands() -> Result<Vec<AssistantCommand>, String> {
|
||||||
if let Ok(cpaths) = fs::read_dir(config::COMMANDS_PATH) {
|
if let Ok(cpaths) = fs::read_dir(config::COMMANDS_PATH) {
|
||||||
for cpath in cpaths {
|
for cpath in cpaths {
|
||||||
// validate this command, check if required files exists
|
// validate this command, check if required files exists
|
||||||
let _cpath = cpath.unwrap().path();
|
let _cpath = match cpath {
|
||||||
|
Ok(entry) => entry.path(),
|
||||||
|
Err(e) => {
|
||||||
|
warn!("Failed to read command directory entry: {}", e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
let cc_file = Path::new(&_cpath).join("command.yaml");
|
let cc_file = Path::new(&_cpath).join("command.yaml");
|
||||||
|
|
||||||
if cc_file.exists() {
|
if cc_file.exists() {
|
||||||
|
|
@ -53,7 +59,7 @@ pub fn parse_commands() -> Result<Vec<AssistantCommand>, String> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if commands.len() > 0 {
|
if !commands.is_empty() {
|
||||||
Ok(commands)
|
Ok(commands)
|
||||||
} else {
|
} else {
|
||||||
error!("No commands were found");
|
error!("No commands were found");
|
||||||
|
|
@ -101,7 +107,7 @@ pub fn fetch_command<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((cmd_path, scmd)) = result_scmd {
|
if let Some((cmd_path, scmd)) = result_scmd {
|
||||||
println!("Ratio is: {}", current_max_ratio);
|
debug!("Ratio is: {}", current_max_ratio);
|
||||||
info!(
|
info!(
|
||||||
"CMD is: {cmd_path:?}, SCMD is: {scmd:?}, Ratio is: {}",
|
"CMD is: {cmd_path:?}, SCMD is: {scmd:?}, Ratio is: {}",
|
||||||
current_max_ratio
|
current_max_ratio
|
||||||
|
|
@ -118,7 +124,7 @@ pub fn execute_exe(exe: &str, args: &Vec<String>) -> std::io::Result<Child> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute_cli(cmd: &str, args: &Vec<String>) -> std::io::Result<Child> {
|
pub fn execute_cli(cmd: &str, args: &Vec<String>) -> std::io::Result<Child> {
|
||||||
println!("Spawning cmd as: cmd /C {} {:?}", cmd, args);
|
debug!("Spawning cmd as: cmd /C {} {:?}", cmd, args);
|
||||||
|
|
||||||
if cfg!(target_os = "windows") {
|
if cfg!(target_os = "windows") {
|
||||||
Command::new("cmd").arg("/C").arg(cmd).args(args).spawn()
|
Command::new("cmd").arg("/C").arg(cmd).args(args).spawn()
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ static WAKE_WORD_ENGINE: OnceCell<WakeWordEngine> = OnceCell::new();
|
||||||
static LISTENING: AtomicBool = AtomicBool::new(false);
|
static LISTENING: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
pub fn init() -> Result<(), ()> {
|
pub fn init() -> Result<(), ()> {
|
||||||
if !WAKE_WORD_ENGINE.get().is_none() {
|
if WAKE_WORD_ENGINE.get().is_some() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} // already initialized
|
} // already initialized
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,10 @@ pub fn init() -> Result<(), ()> {
|
||||||
|
|
||||||
// load wake word files
|
// load wake word files
|
||||||
for rpw in rustpotter_wake_word_files {
|
for rpw in rustpotter_wake_word_files {
|
||||||
rinstance.add_wakeword_from_file(rpw, rpw).unwrap(); // @TODO: Change wakeword key to something else?
|
// @TODO: Change wakeword key to something else?
|
||||||
|
if let Err(e) = rinstance.add_wakeword_from_file(rpw, rpw) {
|
||||||
|
error!("Failed to load wakeword file '{}': {}", rpw, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// store
|
// store
|
||||||
|
|
@ -52,7 +55,8 @@ pub fn init() -> Result<(), ()> {
|
||||||
pub fn data_callback(frame_buffer: &[i16]) -> Option<i32> {
|
pub fn data_callback(frame_buffer: &[i16]) -> Option<i32> {
|
||||||
let mut lock = RUSTPOTTER.get().unwrap().lock();
|
let mut lock = RUSTPOTTER.get().unwrap().lock();
|
||||||
let rustpotter = lock.as_mut().unwrap();
|
let rustpotter = lock.as_mut().unwrap();
|
||||||
let detection = rustpotter.process_samples(frame_buffer.to_vec()); // @TODO. Temp crutch. Fix optimization issue, frame_buffer should not be copied to a new vector!
|
// let detection = rustpotter.process_samples(frame_buffer.to_vec()); // @TODO. Temp crutch. Fix optimization issue, frame_buffer should not be copied to a new vector!
|
||||||
|
let detection = rustpotter.process_samples(frame_buffer);
|
||||||
|
|
||||||
if let Some(detection) = detection {
|
if let Some(detection) = detection {
|
||||||
if detection.score > config::RUSPOTTER_MIN_SCORE {
|
if detection.score > config::RUSPOTTER_MIN_SCORE {
|
||||||
|
|
|
||||||
|
|
@ -175,7 +175,7 @@ pub fn start_recording(device_index: i32, frame_length: u32) {
|
||||||
pub fn stop_recording() {
|
pub fn stop_recording() {
|
||||||
// ensure microphone is initialized
|
// ensure microphone is initialized
|
||||||
RECORDER.with(|recorder| {
|
RECORDER.with(|recorder| {
|
||||||
if !recorder.get().is_none() && IS_RECORDING.load(Ordering::SeqCst) {
|
if recorder.get().is_some() && IS_RECORDING.load(Ordering::SeqCst) {
|
||||||
// pause instead of stop
|
// pause instead of stop
|
||||||
match recorder.get().unwrap().load().pause() {
|
match recorder.get().unwrap().load().pause() {
|
||||||
Err(msg) => {
|
Err(msg) => {
|
||||||
|
|
|
||||||
|
|
@ -159,7 +159,7 @@ where
|
||||||
pub fn read_microphone(frame_buffer: &mut [i16]) {
|
pub fn read_microphone(frame_buffer: &mut [i16]) {
|
||||||
// ensure microphone is initialized
|
// ensure microphone is initialized
|
||||||
RECORDER.with(|r| {
|
RECORDER.with(|r| {
|
||||||
if !r.get().is_none() {
|
if r.get().is_some() {
|
||||||
let cell = r.get().unwrap().load();
|
let cell = r.get().unwrap().load();
|
||||||
let mut lock = cell.lock();
|
let mut lock = cell.lock();
|
||||||
let stream = lock.as_mut().unwrap();
|
let stream = lock.as_mut().unwrap();
|
||||||
|
|
@ -194,7 +194,7 @@ pub fn start_recording(device_index: i32, frame_length: u32) {
|
||||||
|
|
||||||
pub fn stop_recording() {
|
pub fn stop_recording() {
|
||||||
RECORDER.with(|r| {
|
RECORDER.with(|r| {
|
||||||
if !r.get().is_none() && IS_RECORDING.load(Ordering::SeqCst) {
|
if r.get().is_some() && IS_RECORDING.load(Ordering::SeqCst) {
|
||||||
// stop recording
|
// stop recording
|
||||||
let pa = r.get().unwrap().load();
|
let pa = r.get().unwrap().load();
|
||||||
r.get().unwrap().load().lock().unwrap().stop().expect("Failed to stop audio recording!");
|
r.get().unwrap().load().lock().unwrap().stop().expect("Failed to stop audio recording!");
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,11 @@ static RECORDER: OnceCell<PvRecorder> = OnceCell::new();
|
||||||
static IS_RECORDING: AtomicBool = AtomicBool::new(false);
|
static IS_RECORDING: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
pub fn init_microphone(device_index: i32, frame_length: u32) -> bool {
|
pub fn init_microphone(device_index: i32, frame_length: u32) -> bool {
|
||||||
match RECORDER.get().is_none() {
|
if RECORDER.get().is_some() {
|
||||||
true => {
|
return true; // already initialized
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize
|
||||||
let pv_recorder = PvRecorderBuilder::new(frame_length as i32)
|
let pv_recorder = PvRecorderBuilder::new(frame_length as i32)
|
||||||
.device_index(device_index)
|
.device_index(device_index)
|
||||||
// .frame_length(frame_length as i32)
|
// .frame_length(frame_length as i32)
|
||||||
|
|
@ -28,14 +31,11 @@ pub fn init_microphone(device_index: i32, frame_length: u32) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
_ => true, // already initialized
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_microphone(frame_buffer: &mut [i16]) {
|
pub fn read_microphone(frame_buffer: &mut [i16]) {
|
||||||
// ensure microphone is initialized
|
// ensure microphone is initialized
|
||||||
if !RECORDER.get().is_none() {
|
if RECORDER.get().is_some() {
|
||||||
// read to frame buffer
|
// read to frame buffer
|
||||||
|
|
||||||
let frame = RECORDER.get().unwrap().read();
|
let frame = RECORDER.get().unwrap().read();
|
||||||
|
|
@ -68,7 +68,7 @@ pub fn start_recording(device_index: i32, frame_length: u32) -> Result<(), ()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(msg) => {
|
Err(msg) => {
|
||||||
error!("Failed to start audio recording!");
|
error!("Failed to START audio recording: {}", msg);
|
||||||
|
|
||||||
// fail
|
// fail
|
||||||
Err(())
|
Err(())
|
||||||
|
|
@ -78,7 +78,7 @@ pub fn start_recording(device_index: i32, frame_length: u32) -> Result<(), ()> {
|
||||||
|
|
||||||
pub fn stop_recording() -> Result<(), ()> {
|
pub fn stop_recording() -> Result<(), ()> {
|
||||||
// ensure microphone is initialized & recording is in process
|
// ensure microphone is initialized & recording is in process
|
||||||
if !RECORDER.get().is_none() && IS_RECORDING.load(Ordering::SeqCst) {
|
if RECORDER.get().is_some() && IS_RECORDING.load(Ordering::SeqCst) {
|
||||||
// stop recording
|
// stop recording
|
||||||
match RECORDER.get().unwrap().stop() {
|
match RECORDER.get().unwrap().stop() {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
|
|
@ -91,7 +91,7 @@ pub fn stop_recording() -> Result<(), ()> {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
Err(msg) => {
|
Err(msg) => {
|
||||||
error!("Failed to stop audio recording!");
|
error!("Failed to STOP audio recording: {}", msg);
|
||||||
|
|
||||||
// fail
|
// fail
|
||||||
return Err(());
|
return Err(());
|
||||||
|
|
@ -106,7 +106,10 @@ pub fn list_audio_devices() -> Vec<String> {
|
||||||
let audio_devices = PvRecorderBuilder::default().get_available_devices();
|
let audio_devices = PvRecorderBuilder::default().get_available_devices();
|
||||||
match audio_devices {
|
match audio_devices {
|
||||||
Ok(audio_devices) => audio_devices,
|
Ok(audio_devices) => audio_devices,
|
||||||
Err(err) => panic!("Failed to get audio devices: {}", err),
|
Err(err) => {
|
||||||
|
error!("Failed to get audio devices: {}", err);
|
||||||
|
Vec::new()
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use crate::config::structs::SpeechToTextEngine;
|
||||||
static STT_TYPE: OnceCell<SpeechToTextEngine> = OnceCell::new();
|
static STT_TYPE: OnceCell<SpeechToTextEngine> = OnceCell::new();
|
||||||
|
|
||||||
pub fn init() -> Result<(), ()> {
|
pub fn init() -> Result<(), ()> {
|
||||||
if !STT_TYPE.get().is_none() {
|
if STT_TYPE.get().is_some() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} // already initialized
|
} // already initialized
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ static MODEL: OnceCell<Model> = OnceCell::new();
|
||||||
static RECOGNIZER: OnceCell<Mutex<Recognizer>> = OnceCell::new();
|
static RECOGNIZER: OnceCell<Mutex<Recognizer>> = OnceCell::new();
|
||||||
|
|
||||||
pub fn init_vosk() {
|
pub fn init_vosk() {
|
||||||
if !RECOGNIZER.get().is_none() {
|
if RECOGNIZER.get().is_some() {
|
||||||
return;
|
return;
|
||||||
} // already initialized
|
} // already initialized
|
||||||
|
|
||||||
|
|
@ -53,7 +53,6 @@ pub fn recognize(data: &[i16], include_partial: bool) -> Option<String> {
|
||||||
}
|
}
|
||||||
DecodingState::Finalized => {
|
DecodingState::Finalized => {
|
||||||
// Result will always be multiple because we called set_max_alternatives
|
// Result will always be multiple because we called set_max_alternatives
|
||||||
Some(
|
|
||||||
RECOGNIZER
|
RECOGNIZER
|
||||||
.get()
|
.get()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
@ -61,13 +60,7 @@ pub fn recognize(data: &[i16], include_partial: bool) -> Option<String> {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.result()
|
.result()
|
||||||
.multiple()
|
.multiple()
|
||||||
.unwrap()
|
.and_then(|m| m.alternatives.first().map(|a| a.text.to_string()))
|
||||||
.alternatives
|
|
||||||
.first()
|
|
||||||
.unwrap()
|
|
||||||
.text
|
|
||||||
.into(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
DecodingState::Failed => None,
|
DecodingState::Failed => None,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue