summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2023-06-28 21:24:56 -0700
committeryum <yum.food.vr@gmail.com>2023-06-28 21:24:56 -0700
commitbdaeb1911297d7901a12e3ac51b38c3463789279 (patch)
treeb6151c80100db635ca0c4479d8b1afde838b579e
parentff7eb3c212195af71cd0ce4a3cd0c9a081d6ebda (diff)
Add profanity filter
Add toggle to UI to enable a profanity filter. It replaces vowels in bad words with asterisks. Bugfix: filters now apply to OBS
-rw-r--r--GUI/GUI/GUI/Config.cpp3
-rw-r--r--GUI/GUI/GUI/Config.h1
-rw-r--r--GUI/GUI/GUI/Frame.cpp18
-rw-r--r--GUI/GUI/GUI/Frame.h1
-rw-r--r--GUI/GUI/GUI/PythonWrapper.cpp1
-rw-r--r--GUI/package.ps117
-rw-r--r--Scripts/transcribe.py40
7 files changed, 76 insertions, 5 deletions
diff --git a/GUI/GUI/GUI/Config.cpp b/GUI/GUI/GUI/Config.cpp
index d337f77..b73f383 100644
--- a/GUI/GUI/GUI/Config.cpp
+++ b/GUI/GUI/GUI/Config.cpp
@@ -79,6 +79,7 @@ AppConfig::AppConfig(wxTextCtrl* out)
remove_trailing_period(false),
enable_uppercase_filter(false),
enable_lowercase_filter(false),
+ enable_profanity_filter(false),
enable_debug_mode(false),
reset_on_toggle(true),
gpu_idx(0),
@@ -132,6 +133,7 @@ bool AppConfig::Serialize(const std::filesystem::path& path) {
cm.Set("remove_trailing_period", remove_trailing_period);
cm.Set("enable_uppercase_filter", enable_uppercase_filter);
cm.Set("enable_lowercase_filter", enable_lowercase_filter);
+ cm.Set("enable_profanity_filter", enable_profanity_filter);
cm.Set("enable_debug_mode", enable_debug_mode);
cm.Set("reset_on_toggle", reset_on_toggle);
cm.Set("gpu_idx", gpu_idx);
@@ -198,6 +200,7 @@ bool AppConfig::Deserialize(const std::filesystem::path& path) {
cm.Get("remove_trailing_period", c.remove_trailing_period);
cm.Get("enable_uppercase_filter", c.enable_uppercase_filter);
cm.Get("enable_lowercase_filter", c.enable_lowercase_filter);
+ cm.Get("enable_profanity_filter", c.enable_profanity_filter);
cm.Get("enable_debug_mode", c.enable_debug_mode);
cm.Get("reset_on_toggle", c.reset_on_toggle);
cm.Get("gpu_idx", c.gpu_idx);
diff --git a/GUI/GUI/GUI/Config.h b/GUI/GUI/GUI/Config.h
index e4a9bf4..213ce57 100644
--- a/GUI/GUI/GUI/Config.h
+++ b/GUI/GUI/GUI/Config.h
@@ -65,6 +65,7 @@ public:
bool remove_trailing_period;
bool enable_uppercase_filter;
bool enable_lowercase_filter;
+ bool enable_profanity_filter;
bool enable_debug_mode;
bool reset_on_toggle;
int gpu_idx;
diff --git a/GUI/GUI/GUI/Frame.cpp b/GUI/GUI/GUI/Frame.cpp
index 706165b..69def6b 100644
--- a/GUI/GUI/GUI/Frame.cpp
+++ b/GUI/GUI/GUI/Frame.cpp
@@ -47,6 +47,7 @@ namespace {
ID_PY_APP_REMOVE_TRAILING_PERIOD,
ID_PY_APP_ENABLE_UPPERCASE_FILTER,
ID_PY_APP_ENABLE_LOWERCASE_FILTER,
+ ID_PY_APP_ENABLE_PROFANITY_FILTER,
ID_PY_APP_ENABLE_DEBUG_MODE,
ID_PY_APP_RESET_ON_TOGGLE,
ID_PY_APP_ROWS,
@@ -882,6 +883,16 @@ Frame::Frame()
);
py_app_enable_lowercase_filter_ = py_app_enable_lowercase_filter;
+ auto* py_app_enable_profanity_filter = new wxCheckBox(py_config_panel,
+ ID_PY_APP_ENABLE_PROFANITY_FILTER, "Enable profanity filter");
+ py_app_enable_profanity_filter->SetValue(app_c_->enable_profanity_filter);
+ py_app_enable_profanity_filter->SetToolTip(
+ "If checked, profane words in your transcript will have "
+ "their vowels replaced with asterisks. Currently only "
+ "English is supported."
+ );
+ py_app_enable_profanity_filter_ = py_app_enable_profanity_filter;
+
auto* py_app_enable_debug_mode = new wxCheckBox(py_config_panel,
ID_PY_APP_ENABLE_DEBUG_MODE, "Enable debug mode");
py_app_enable_debug_mode->SetValue(app_c_->enable_debug_mode);
@@ -933,6 +944,8 @@ Frame::Frame()
/*flags=*/wxEXPAND);
sizer->Add(py_app_enable_lowercase_filter, /*proportion=*/0,
/*flags=*/wxEXPAND);
+ sizer->Add(py_app_enable_profanity_filter, /*proportion=*/0,
+ /*flags=*/wxEXPAND);
sizer->Add(py_app_enable_debug_mode, /*proportion=*/0,
/*flags=*/wxEXPAND);
sizer->Add(py_app_start_button, /*proportion=*/0,
@@ -1453,6 +1466,9 @@ void Frame::ApplyConfigToInputFields()
auto* py_app_enable_lowercase_filter = static_cast<wxCheckBox*>(FindWindowById(ID_PY_APP_ENABLE_LOWERCASE_FILTER));
py_app_enable_lowercase_filter->SetValue(app_c_->enable_lowercase_filter);
+ auto* py_app_enable_profanity_filter = static_cast<wxCheckBox*>(FindWindowById(ID_PY_APP_ENABLE_PROFANITY_FILTER));
+ py_app_enable_profanity_filter->SetValue(app_c_->enable_profanity_filter);
+
auto* py_app_enable_debug_mode = static_cast<wxCheckBox*>(FindWindowById(ID_PY_APP_ENABLE_DEBUG_MODE));
py_app_enable_debug_mode->SetValue(app_c_->enable_debug_mode);
@@ -2044,6 +2060,7 @@ void Frame::OnAppStart(wxCommandEvent& event) {
const bool remove_trailing_period = py_app_remove_trailing_period_->GetValue();
const bool enable_uppercase_filter = py_app_enable_uppercase_filter_->GetValue();
const bool enable_lowercase_filter = py_app_enable_lowercase_filter_->GetValue();
+ const bool enable_profanity_filter = py_app_enable_profanity_filter_->GetValue();
const bool enable_debug_mode = py_app_enable_debug_mode_->GetValue();
const bool reset_on_toggle = py_app_reset_on_toggle_->GetValue();
std::string rows_str = py_app_rows_->GetValue().ToStdString();
@@ -2143,6 +2160,7 @@ void Frame::OnAppStart(wxCommandEvent& event) {
app_c_->remove_trailing_period = remove_trailing_period;
app_c_->enable_uppercase_filter = enable_uppercase_filter;
app_c_->enable_lowercase_filter = enable_lowercase_filter;
+ app_c_->enable_profanity_filter = enable_profanity_filter;
app_c_->enable_debug_mode = enable_debug_mode;
app_c_->reset_on_toggle = reset_on_toggle;
app_c_->gpu_idx = gpu_idx;
diff --git a/GUI/GUI/GUI/Frame.h b/GUI/GUI/GUI/Frame.h
index 46f5bcd..bed6cf7 100644
--- a/GUI/GUI/GUI/Frame.h
+++ b/GUI/GUI/GUI/Frame.h
@@ -69,6 +69,7 @@ private:
wxCheckBox* py_app_remove_trailing_period_;
wxCheckBox* py_app_enable_uppercase_filter_;
wxCheckBox* py_app_enable_lowercase_filter_;
+ wxCheckBox* py_app_enable_profanity_filter_;
wxCheckBox* py_app_enable_debug_mode_;
wxCheckBox* py_app_reset_on_toggle_;
wxCheckBox* unity_clear_osc_;
diff --git a/GUI/GUI/GUI/PythonWrapper.cpp b/GUI/GUI/GUI/PythonWrapper.cpp
index c5421e8..6e80744 100644
--- a/GUI/GUI/GUI/PythonWrapper.cpp
+++ b/GUI/GUI/GUI/PythonWrapper.cpp
@@ -493,6 +493,7 @@ std::future<bool> PythonWrapper::StartApp(
"--remove_trailing_period", config.remove_trailing_period ? "1" : "0",
"--enable_uppercase_filter", config.enable_uppercase_filter ? "1" : "0",
"--enable_lowercase_filter", config.enable_lowercase_filter ? "1" : "0",
+ "--enable_profanity_filter", config.enable_profanity_filter ? "1" : "0",
"--enable_debug_mode", config.enable_debug_mode ? "1" : "0",
"--emotes_pickle", kEmotesPickle,
"--gpu_idx", std::to_string(config.gpu_idx),
diff --git a/GUI/package.ps1 b/GUI/package.ps1
index 4800777..db84a6d 100644
--- a/GUI/package.ps1
+++ b/GUI/package.ps1
@@ -133,6 +133,22 @@ if (-Not (Test-Path UwwwuPP)) {
popd > $null
}
+if (-Not (Test-Path Profanity)) {
+ mkdir Profanity
+ pushd Profanity > $null
+
+ $repo = "List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words"
+ git clone https://github.com/LDNOOBW/$repo
+
+ mkdir Profanity
+ cp $repo/LICENSE Profanity/
+ cp $repo/en Profanity/
+
+ echo "Source: https://github.com/LDNOOBW/List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words" > Profanity/AUTHOR
+
+ popd > $null
+}
+
mkdir $install_dir > $null
mkdir $install_dir/Resources > $null
cp -Recurse ../Animations TaSTT/Resources/Animations
@@ -153,6 +169,7 @@ mkdir TaSTT/Resources/Models
mkdir TaSTT/Resources/Uwu
cp UwwwuPP/build/Src/Debug/Uwwwu.exe TaSTT/Resources/Uwu/
cp UwwwuPP/LICENSE TaSTT/Resources/Uwu/
+cp -r Profanity/Profanity TaSTT/Resources/Profanity
if (-Not $skip_zip) {
Compress-Archive -Path "$install_dir" -DestinationPath "$install_dir.zip" -Force
diff --git a/Scripts/transcribe.py b/Scripts/transcribe.py
index 28b6ca0..d937cb6 100644
--- a/Scripts/transcribe.py
+++ b/Scripts/transcribe.py
@@ -6,6 +6,7 @@ from faster_whisper import WhisperModel
from functools import partial
from math import ceil
from playsound import playsound
+from profanity_filter import ProfanityFilter
from sentence_splitter import split_text_into_sentences
import argparse
@@ -67,6 +68,11 @@ class AudioState:
# gets appended to `text`.
self.commit_fuzz_threshold = 8
+ # If set, profanity in transcriptions will have their vowels replaced
+ # with asterisks. Only works in English.
+ self.enable_profanity_filter = False
+ self.profanity_filter: ProfanityFilter = None
+
# List of:
# List of tuples of:
# Segment start time, end time, and text
@@ -154,7 +160,7 @@ def onAudioFramesAvailable(
return (frames, pyaudio.paContinue)
-def getMicStream(which_mic):
+def getMicStream(which_mic) -> AudioState:
audio_state = AudioState()
audio_state.p = pyaudio.PyAudio()
@@ -346,10 +352,11 @@ def transcribeAudio(audio_state,
audio_state.preview_text = audio_state.text + preview_text
now = time.time()
- print("Transcription ({} seconds): {}".format(
- now - last_transcribe_time,
- audio_state.preview_text))
- last_transcribe_time = now
+ if audio_state.enable_debug_mode:
+ print("Raw transcription ({} seconds): {}".format(
+ now - last_transcribe_time,
+ audio_state.preview_text))
+ last_transcribe_time = now
# Translate if requested.
translated = audio_state.preview_text
@@ -388,8 +395,16 @@ def transcribeAudio(audio_state,
filtered_text = filtered_text.upper()
if enable_lowercase_filter:
filtered_text = filtered_text.lower()
+ if audio_state.enable_profanity_filter:
+ filtered_text = audio_state.profanity_filter.filter(filtered_text)
audio_state.filtered_text = filtered_text
+ now = time.time()
+ print("Transcription ({} seconds): {}".format(
+ now - last_transcribe_time,
+ filtered_text))
+ last_transcribe_time = now
+
if old_text != audio_state.preview_text:
# We think the user said something, so reset the amount of
# time we sleep between transcriptions to the minimum.
@@ -618,6 +633,7 @@ def transcribeLoop(mic: str,
remove_trailing_period: bool,
enable_uppercase_filter: bool,
enable_lowercase_filter: bool,
+ enable_profanity_filter: bool,
enable_debug_mode: bool,
button: str,
estate: EmotesState,
@@ -633,6 +649,13 @@ def transcribeLoop(mic: str,
audio_state.reset_on_toggle = reset_on_toggle
audio_state.commit_fuzz_threshold = commit_fuzz_threshold
audio_state.enable_debug_mode = enable_debug_mode
+ audio_state.enable_profanity_filter = enable_profanity_filter
+
+ # Set up profanity filter
+ en_profanity_path = os.path.abspath("Resources/Profanity/en")
+ audio_state.profanity_filter = ProfanityFilter(en_profanity_path)
+ if enable_profanity_filter:
+ audio_state.profanity_filter.load()
lang_bits = language_target.split(" | ")
if len(lang_bits) == 2:
@@ -780,6 +803,7 @@ if __name__ == "__main__":
parser.add_argument("--remove_trailing_period", type=int, help="If set to 1, trailing period will be removed.")
parser.add_argument("--enable_uppercase_filter", type=int, help="If set to 1, transcriptions will be converted to UPPERCASE.")
parser.add_argument("--enable_lowercase_filter", type=int, help="If set to 1, transcriptions will be converted to lowercase.")
+ parser.add_argument("--enable_profanity_filter", type=int, help="If set to 1, profanity in transcriptions will have their vowels replaced with asterisks. Only works in English.")
parser.add_argument("--button", type=str, help="The controller button used to start/stop transcription. E.g. \"left joystick\"")
parser.add_argument("--emotes_pickle", type=str, help="The path to emotes pickle. See emotes_v2.py for details.")
parser.add_argument("--gpu_idx", type=str, help="The index of the GPU device to use. On single GPU systems, use 0.")
@@ -870,6 +894,11 @@ if __name__ == "__main__":
else:
args.enable_lowercase_filter = False
+ if args.enable_profanity_filter == 1:
+ args.enable_profanity_filter = True
+ else:
+ args.enable_profanity_filter = False
+
if args.enable_debug_mode == 1:
args.enable_debug_mode = True
else:
@@ -896,6 +925,7 @@ if __name__ == "__main__":
args.remove_trailing_period,
args.enable_uppercase_filter,
args.enable_lowercase_filter,
+ args.enable_profanity_filter,
args.enable_debug_mode,
args.button,
estate, window_duration_s,