diff options
| author | yum <yum.food.vr@gmail.com> | 2023-01-04 09:52:02 -0800 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2023-01-04 10:03:39 -0800 |
| commit | 66d311b3267620995e5c35b16f3fba18ed0c48f3 (patch) | |
| tree | 88411e37c442d66cc34e3f6f22683ce2976a5743 | |
| parent | 6bed3a15edf134fa176ca4866b4346017bc97ada (diff) | |
Bugfix: user-provided paths may now contain spaces
Previously, paths containing spaces would be interpreted by python's argument
parser as multiple separate arguments, causing it to fail. Now we escape paths
inside PythonWrapper using std::quoted().
* Improve PII filtering. Python output would contain multiple path separators
(like C:\\Users\\foo\\), defeating the PII regex.
* Silence compiler warning in PII filter.
* Document usability improvements.
* Transcription layer exponential backoff goes to ~infinity when paused.
This is a hack, since we really don't need to transcribe at all when paused,
but it lets us keep the code simple. Good enough until the next rewrite.
* Shader only samples background when necessary.
* Limit matchStrings() print()s to DEBUG mode
| -rw-r--r-- | GUI/GUI/GUI/Frame.cpp | 60 | ||||
| -rw-r--r-- | GUI/GUI/GUI/Logging.cpp | 5 | ||||
| -rw-r--r-- | GUI/GUI/GUI/PythonWrapper.cpp | 65 | ||||
| -rw-r--r-- | GUI/GUI/GUI/PythonWrapper.h | 9 | ||||
| -rw-r--r-- | README.md | 5 | ||||
| -rw-r--r-- | Scripts/string_matcher.py | 10 | ||||
| -rw-r--r-- | Scripts/transcribe.py | 13 | ||||
| -rw-r--r-- | Shaders/TaSTT_template.shader | 3 |
8 files changed, 93 insertions, 77 deletions
diff --git a/GUI/GUI/GUI/Frame.cpp b/GUI/GUI/GUI/Frame.cpp index cfb2060..5fb8dd9 100644 --- a/GUI/GUI/GUI/Frame.cpp +++ b/GUI/GUI/GUI/Frame.cpp @@ -730,46 +730,40 @@ void Frame::OnDumpMics(wxCommandEvent& event) Log(transcribe_out_, "{}\n", PythonWrapper::DumpMics());
}
-#define DEBUG
+bool GetUserPath(const std::string& raw, std::filesystem::path& clean, const std::string& err_prefix = "", bool must_exist = true) {
+ clean = raw;
+ if (must_exist && !std::filesystem::exists(clean)) {
+ std::ostringstream oss;
+ oss << err_prefix << ": User-provided path does not exist at " << clean << std::endl;
+ wxLogError(oss.str().c_str());
+ return false;
+ }
+ return true;
+}
void Frame::OnGenerateFX(wxCommandEvent& event)
{
- std::filesystem::path unity_assets_path = unity_assets_file_picker_->GetPath().ToStdString();
-#ifndef DEBUG
- if (!std::filesystem::exists(unity_assets_path)) {
- std::ostringstream oss;
- oss << "Cannot generate FX layer: assets directory does not exist at " << unity_assets_path << std::endl;
- wxLogError(oss.str().c_str());
+ std::filesystem::path unity_assets_path;
+ if (!GetUserPath(unity_assets_file_picker_->GetPath().ToStdString(), unity_assets_path,
+ "Cannot generate FX layer: Failed to validate assets directory")) {
return;
}
-#endif
- std::filesystem::path unity_animator_path = unity_animator_file_picker_->GetPath().ToStdString();
-#ifndef DEBUG
- if (!std::filesystem::exists(unity_animator_path)) {
- std::ostringstream oss;
- oss << "Cannot generate FX layer: animator does not exist at " << unity_animator_path << std::endl;
- wxLogError(oss.str().c_str());
+ std::filesystem::path unity_animator_path;
+ if (!GetUserPath(unity_animator_file_picker_->GetPath().ToStdString(), unity_animator_path,
+ "Cannot generate FX layer: Failed to validate animator directory")) {
return;
}
-#endif
- std::filesystem::path unity_parameters_path = unity_parameters_file_picker_->GetPath().ToStdString();
-#ifndef DEBUG
- if (!std::filesystem::exists(unity_parameters_path)) {
- std::ostringstream oss;
- oss << "Cannot generate FX layer: parameters do not exist at " << unity_parameters_path << std::endl;
- wxLogError(oss.str().c_str());
+ std::filesystem::path unity_parameters_path;
+ if (!GetUserPath(unity_parameters_file_picker_->GetPath().ToStdString(), unity_parameters_path,
+ "Cannot generate FX layer: Failed to validate parameters directory")) {
return;
}
-#endif
- std::filesystem::path unity_menu_path = unity_menu_file_picker_->GetPath().ToStdString();
-#ifndef DEBUG
- if (!std::filesystem::exists(unity_menu_path)) {
- std::ostringstream oss;
- oss << "Cannot generate FX layer: menu does not exist at " << unity_menu_path << std::endl;
- wxLogError(oss.str().c_str());
+ std::filesystem::path unity_menu_path;
+ if (!GetUserPath(unity_menu_file_picker_->GetPath().ToStdString(), unity_menu_path,
+ "Cannot generate FX layer: Failed to validate menu directory")) {
return;
}
-#endif
+
std::string unity_animator_generated_dir = unity_animator_generated_dir_->GetLineText(0).ToStdString();
std::string unity_animator_generated_name = unity_animator_generated_name_->GetLineText(0).ToStdString();
std::string unity_parameters_generated_name = unity_parameters_generated_name_->GetLineText(0).ToStdString();
@@ -804,10 +798,10 @@ void Frame::OnGenerateFX(wxCommandEvent& event) std::string out;
if (!PythonWrapper::GenerateAnimator(
- unity_assets_path.string(),
- unity_animator_path.string(),
- unity_parameters_path.string(),
- unity_menu_path.string(),
+ unity_assets_path,
+ unity_animator_path,
+ unity_parameters_path,
+ unity_menu_path,
unity_animator_generated_dir,
unity_animator_generated_name,
unity_parameters_generated_name,
diff --git a/GUI/GUI/GUI/Logging.cpp b/GUI/GUI/GUI/Logging.cpp index 6727ba1..b9f3be4 100644 --- a/GUI/GUI/GUI/Logging.cpp +++ b/GUI/GUI/GUI/Logging.cpp @@ -6,12 +6,13 @@ std::string Logging::HidePII(const std::string&& str,
const std::string& replacement) {
try {
- std::regex c_users("(C:\\\\Users\\\\)[a-zA-Z0-9_]+");
+ std::regex c_users("(C:\\\\+Users\\\\+)[a-zA-Z0-9_ ]+");
std::string real_replacement = "$1" + replacement;
return std::regex_replace(str, c_users, real_replacement);
}
- catch (const std::regex_error& e) {
+ catch (const std::exception& e) {
wxLogFatalError(e.what());
}
wxLogFatalError("Unhandled regex error (HidePII)");
+ return ""; // Compiler thinks we can get here (we can't) and prints a warning.
}
diff --git a/GUI/GUI/GUI/PythonWrapper.cpp b/GUI/GUI/GUI/PythonWrapper.cpp index 81366e5..a38ee4a 100644 --- a/GUI/GUI/GUI/PythonWrapper.cpp +++ b/GUI/GUI/GUI/PythonWrapper.cpp @@ -163,11 +163,18 @@ wxProcess* PythonWrapper::StartApp( std::move(exit_callback)); } +// Wrap the filesystem path in quotes, escaping intermediate quotes with \\. +std::string Quote(const std::filesystem::path& p) { + std::ostringstream oss; + oss << std::quoted(p.string()); + return oss.str(); +} + bool PythonWrapper::GenerateAnimator( - const std::string& unity_assets_path, - const std::string& unity_animator_path, - const std::string& unity_parameters_path, - const std::string& unity_menu_path, + const std::filesystem::path& unity_assets_path, + const std::filesystem::path& unity_animator_path, + const std::filesystem::path& unity_parameters_path, + const std::filesystem::path& unity_menu_path, const std::string& unity_animator_generated_dir, const std::string& unity_animator_generated_name, const std::string& unity_parameters_generated_name, @@ -305,9 +312,9 @@ bool PythonWrapper::GenerateAnimator( { Log(out, "Generating guid.map... "); std::string py_stdout, py_stderr; - if (InvokeWithArgs({ libunity_path, "guid_map", - "--project_root", unity_assets_path, - "--save_to", guid_map_path.string() }, + if (PythonWrapper::InvokeWithArgs({ libunity_path, "guid_map", + "--project_root", Quote(unity_assets_path), + "--save_to", Quote(guid_map_path), }, &py_stdout, &py_stderr)) { Log(out, "success!\n"); Log(out, py_stdout.c_str()); @@ -329,8 +336,8 @@ bool PythonWrapper::GenerateAnimator( Log(out, "Generating animations... "); std::string py_stdout, py_stderr; if (InvokeWithArgs({ libtastt_path, "gen_anims", - "--gen_anim_dir", tastt_animations_path.string(), - "--guid_map", guid_map_path.string(), + "--gen_anim_dir", Quote(tastt_animations_path), + "--guid_map", Quote(guid_map_path), "--chars_per_sync", chars_per_sync, "--bytes_per_char", bytes_per_char, "--rows", std::to_string(rows), @@ -356,9 +363,9 @@ bool PythonWrapper::GenerateAnimator( Log(out, "Generating FX layer... "); std::string py_stdout, py_stderr; if (InvokeWithArgs({ libtastt_path, "gen_fx", - "--fx_dest", tastt_fx0_path.string(), - "--gen_anim_dir", tastt_animations_path.string(), - "--guid_map", guid_map_path.string(), + "--fx_dest", Quote(tastt_fx0_path), + "--gen_anim_dir", Quote(tastt_animations_path), + "--guid_map", Quote(guid_map_path), "--chars_per_sync", chars_per_sync, "--bytes_per_char", bytes_per_char, "--rows", std::to_string(rows), @@ -384,10 +391,10 @@ bool PythonWrapper::GenerateAnimator( Log(out, "Adding enable/disable toggle... "); std::string py_stdout, py_stderr; if (InvokeWithArgs({ libunity_path, "add_toggle", - "--fx0", tastt_fx0_path.string(), - "--fx_dest", tastt_fx1_path.string(), - "--gen_anim_dir", tastt_animations_path.string(), - "--guid_map", guid_map_path.string() }, + "--fx0", Quote(tastt_fx0_path), + "--fx_dest", Quote(tastt_fx1_path), + "--gen_anim_dir", Quote(tastt_animations_path), + "--guid_map", Quote(guid_map_path), }, &py_stdout, &py_stderr)) { Log(out, "success!\n"); Log(out, py_stdout.c_str()); @@ -409,9 +416,9 @@ bool PythonWrapper::GenerateAnimator( Log(out, "Merging with user animator... "); std::string py_stdout, py_stderr; if (InvokeWithArgs({ libunity_path, "merge", - "--fx0", unity_animator_path, - "--fx1", tastt_fx1_path.string(), - "--fx_dest", tastt_fx2_path.string() }, + "--fx0", Quote(unity_animator_path), + "--fx1", Quote(tastt_fx1_path), + "--fx_dest", Quote(tastt_fx2_path), }, &py_stdout, &py_stderr)) { Log(out, "success!\n"); Log(out, py_stdout.c_str()); @@ -433,10 +440,10 @@ bool PythonWrapper::GenerateAnimator( Log(out, "Setting noop animations... "); std::string py_stdout, py_stderr; if (InvokeWithArgs({ libunity_path, "set_noop_anim", - "--fx0", tastt_fx2_path.string(), - "--fx_dest", tastt_animator_path.string(), - "--gen_anim_dir", tastt_animations_path.string(), - "--guid_map", guid_map_path.string() }, + "--fx0", Quote(tastt_fx2_path), + "--fx_dest", Quote(tastt_animator_path), + "--gen_anim_dir", Quote(tastt_animations_path), + "--guid_map", Quote(guid_map_path), }, &py_stdout, &py_stderr)) { Log(out, "success!\n"); Log(out, py_stdout.c_str()); @@ -458,8 +465,8 @@ bool PythonWrapper::GenerateAnimator( Log(out, "Generating avatar parameters... "); std::string py_stdout, py_stderr; if (InvokeWithArgs({ generate_params_path, - "--old_params", unity_parameters_path, - "--new_params", tastt_params_path.string(), + "--old_params", Quote(unity_parameters_path), + "--new_params", Quote(tastt_params_path), "--chars_per_sync", chars_per_sync, "--bytes_per_char", bytes_per_char }, &py_stdout, &py_stderr)) { @@ -482,9 +489,11 @@ bool PythonWrapper::GenerateAnimator( { Log(out, "Generating avatar menu... "); std::string py_stdout, py_stderr; - if (InvokeWithArgs({ generate_menu_path, - "--old_menu", unity_menu_path, - "--new_menu", tastt_menu_path.string()}, + // No idea why, but inlining this into `InvokeWithArgs` confuses the compiler. + std::vector<std::string> args = { generate_menu_path, + "--old_menu", Quote(unity_menu_path), + "--new_menu", Quote(tastt_menu_path), }; + if (InvokeWithArgs( std::move(args), &py_stdout, &py_stderr)) { Log(out, "success!\n"); Log(out, py_stdout.c_str()); diff --git a/GUI/GUI/GUI/PythonWrapper.h b/GUI/GUI/GUI/PythonWrapper.h index a60bdae..fed8e7b 100644 --- a/GUI/GUI/GUI/PythonWrapper.h +++ b/GUI/GUI/GUI/PythonWrapper.h @@ -8,6 +8,7 @@ #include <wx/process.h> +#include <filesystem> #include <string> #include <vector> @@ -56,10 +57,10 @@ namespace PythonWrapper ); bool GenerateAnimator( - const std::string& unity_assets_path, - const std::string& unity_animator_path, - const std::string& unity_parameters_path, - const std::string& unity_menu_path, + const std::filesystem::path& unity_assets_path, + const std::filesystem::path& unity_animator_path, + const std::filesystem::path& unity_parameters_path, + const std::filesystem::path& unity_menu_path, const std::string& unity_animator_generated_dir, const std::string& unity_animator_generated_name, const std::string& unity_parameters_generated_name, @@ -172,6 +172,11 @@ Contributions welcome. Send a pull request to this repository. checking transcriptions without having to see the board in game. 6. TTS. Multiple people have requested this. See if there are open source algorithms available; or, figure out how to integrate with + 7. Save UI input fields to config file. Persist across process exit. It's + annoying having to re-enter the config every time I use the STT. + 8. Customizable controller bindings. Someone mentioned they use left click + to unmute. Let's work around users, not make them change their existing + keybinds. 4. Optimization 1. ~~Utilize the avatar 3.0 SDK's ability to drive parameters to reduce the total # of parameters (and therefore OSC messages & sync events). Note diff --git a/Scripts/string_matcher.py b/Scripts/string_matcher.py index 686056c..26241f2 100644 --- a/Scripts/string_matcher.py +++ b/Scripts/string_matcher.py @@ -52,7 +52,8 @@ def matchSpaceDelimitedStrings(old_text: str, new_text: str, window_size = 4) -> def matchStrings(old_text: str, new_text: str, window_size = 3) -> str: if old_text == new_text: - print("STRING MATCH exception path 1") + if DEBUG: + print("STRING MATCH exception path 1") return old_text elif len(old_text) >= window_size and len(new_text) >= window_size: # Find the window where the cumulative string distance @@ -105,9 +106,10 @@ def matchStrings(old_text: str, new_text: str, window_size = 3) -> str: new_text[best_match_j:])) return old_prefix + new_text[best_match_j:] else: - print("STRING MATCH exception path 2") - print(" OLD: {}".format(old_text)) - print(" NEW: {}".format(new_text)) + if DEBUG: + print("STRING MATCH exception path 2") + print(" OLD: {}".format(old_text)) + print(" NEW: {}".format(new_text)) return new_text if __name__ == "__main__": diff --git a/Scripts/transcribe.py b/Scripts/transcribe.py index 4d36e53..7f07efe 100644 --- a/Scripts/transcribe.py +++ b/Scripts/transcribe.py @@ -88,7 +88,7 @@ class AudioState: def sleepInterruptible(self, dur_s, stride_ms = 5): dur_ms = dur_s * 1000.0 timeout = time.time() + dur_s - while self.audio_paused and time.time() < timeout: + while self.audio_paused and self.run_app and time.time() < timeout: time.sleep(stride_ms / 1000.0) def dumpMicDevices(): @@ -263,9 +263,14 @@ def transcribeAudio(audio_state, model, use_cpu: bool): audio_state.transcribe_no_change_count += 1 longer_sleep_dur = audio_state.transcribe_sleep_duration longer_sleep_dur += audio_state.transcribe_sleep_duration_min_s * (1.3**audio_state.transcribe_no_change_count) - audio_state.transcribe_sleep_duration = min( - audio_state.transcribe_sleep_duration_max_s, - longer_sleep_dur) + if audio_state.audio_paused: + audio_state.transcribe_sleep_duration = min( + 1000 * 1000, + longer_sleep_dur) + else: + audio_state.transcribe_sleep_duration = min( + audio_state.transcribe_sleep_duration_max_s, + longer_sleep_dur) text = transcribe(audio_state, model, audio_state.frames, use_cpu) if not text: diff --git a/Shaders/TaSTT_template.shader b/Shaders/TaSTT_template.shader index b40df36..26519b5 100644 --- a/Shaders/TaSTT_template.shader +++ b/Shaders/TaSTT_template.shader @@ -405,7 +405,6 @@ letter_uv = GetLetter(uv_with_margin, letter, texture_cols, texture_rows, 8, 4);
}
- fixed4 background = TaSTT_Backplate.Sample(sampler_linear_repeat, uv);
fixed4 text;
int which_texture = (int) floor(letter / (64 * 128));
@@ -438,7 +437,7 @@ }
fixed4 black = fixed4(0,0,0,1);
if (text.r == black.r && text.g == black.g && text.b == black.b && text.a == black.a) {
- return background;
+ return TaSTT_Backplate.Sample(sampler_linear_repeat, uv);
} else {
return text;
}
|
