From 61681895c14923f20dbd21aa821f4d2be8f7635d Mon Sep 17 00:00:00 2001 From: yum Date: Sun, 26 Feb 2023 17:50:02 -0800 Subject: CPP implementation refinements * Pip install, dependency install, and model download can be gracefully interrupted and resume later. * Mic list was pointing at freed memory. Fix this by copying into the heap with std::unique_ptr()s. Mic list in CPP panel is much more reliable now. --- GUI/GUI/GUI/PythonWrapper.cpp | 10 ++++++--- GUI/GUI/GUI/PythonWrapper.h | 5 ++++- GUI/GUI/GUI/WhisperCPP.cpp | 49 +++++++++++++++++++++++++++---------------- GUI/GUI/GUI/WhisperCPP.h | 4 +++- 4 files changed, 45 insertions(+), 23 deletions(-) (limited to 'GUI') diff --git a/GUI/GUI/GUI/PythonWrapper.cpp b/GUI/GUI/GUI/PythonWrapper.cpp index 05c3e48..55c7626 100644 --- a/GUI/GUI/GUI/PythonWrapper.cpp +++ b/GUI/GUI/GUI/PythonWrapper.cpp @@ -264,7 +264,7 @@ bool PythonWrapper::InvokeCommandWithArgs(const std::string& cmd, } } if (!run_cb()) { - return true; + return false; } std::ostringstream stdout_oss, stderr_oss; @@ -379,14 +379,18 @@ bool PythonWrapper::InstallPip(std::string* out, std::string* err) { return ret; } -bool PythonWrapper::InstallPip(const std::function&& out_cb) { +bool PythonWrapper::InstallPip( + const std::function&& out_cb, + const std::function&& in_cb, + const std::function&& run_cb) { std::filesystem::path pip_flag = "Resources/Python/.pip_installed"; if (std::filesystem::exists(pip_flag)) { return true; } std::string pip_path = "Resources/Python/get-pip.py"; - if (!InvokeWithArgs({ pip_path }, std::move(out_cb))) { + if (!InvokeWithArgs({ pip_path }, std::move(out_cb), std::move(in_cb), + std::move(run_cb))) { return false; } diff --git a/GUI/GUI/GUI/PythonWrapper.h b/GUI/GUI/GUI/PythonWrapper.h index f0591c1..edea0df 100644 --- a/GUI/GUI/GUI/PythonWrapper.h +++ b/GUI/GUI/GUI/PythonWrapper.h @@ -60,7 +60,10 @@ namespace PythonWrapper std::string DumpMics(); // Execute get-pip.py. - bool InstallPip(const std::function&& out_cb); + bool InstallPip( + const std::function&& out_cb, + const std::function&& in_cb = [](std::string&) {}, + const std::function&& run_cb = []() { return true; }); bool InstallPip(std::string* out, std::string* err = nullptr); // TODO(yum) both StartApp and GenerateAnimator should be diff --git a/GUI/GUI/GUI/WhisperCPP.cpp b/GUI/GUI/GUI/WhisperCPP.cpp index b969494..3610901 100644 --- a/GUI/GUI/GUI/WhisperCPP.cpp +++ b/GUI/GUI/GUI/WhisperCPP.cpp @@ -113,14 +113,14 @@ bool WhisperCPP::GetMics(std::vector& mics) { return false; } - std::vector mics_raw; + std::vector> mics_raw; if (!GetMicsImpl(mics_raw)) { return false; } mics.clear(); for (const auto& raw_mic : mics_raw) { - mics.push_back(wcharToAsciiString(raw_mic.displayName)); + mics.push_back(wcharToAsciiString(raw_mic->displayName)); } return true; @@ -132,7 +132,7 @@ bool WhisperCPP::OpenMic(const int idx, Whisper::iAudioCapture*& stream) { return false; } - std::vector mics_raw; + std::vector> mics_raw; if (!GetMicsImpl(mics_raw)) { return false; } @@ -144,11 +144,11 @@ bool WhisperCPP::OpenMic(const int idx, Whisper::iAudioCapture*& stream) { Whisper::sCaptureParams params{}; stream = nullptr; - HRESULT err = f_->openCaptureDevice(mics_raw[idx].endpoint, params, + HRESULT err = f_->openCaptureDevice(mics_raw[idx]->endpoint, params, &stream); if (FAILED(err)) { Log(out_, "Failed to open mic with idx {} ({}): {}\n", idx, - wcharToAsciiString(mics_raw[idx].displayName), + wcharToAsciiString(mics_raw[idx]->displayName), hresultToString(err)); return false; } @@ -164,17 +164,20 @@ bool WhisperCPP::InstallDependencies() { return true; } - std::function out_cb = - [&](const std::string& out, const std::string& err) -> void { + auto out_cb = [&](const std::string& out, const std::string& err) -> void { Log(out_, out); Log(out_, err); }; + auto in_cb = [&](std::string& in) {}; + auto run_cb = [&]() -> bool { + return run_transcription_; + }; bool ret = PythonWrapper::InvokeWithArgs({ "-u", // Unbuffered output "-m pip", "install", "-r Resources/Scripts/whisper_requirements.txt", - }, std::move(out_cb)); + }, std::move(out_cb), std::move(in_cb), std::move(run_cb)); if (!ret) { Log(out_, "Failed to install dependencies!\n"); @@ -194,15 +197,20 @@ bool WhisperCPP::DownloadModel(const std::string& model_name, url_oss << "https://huggingface.co/datasets/ggerganov/whisper.cpp/resolve/main/"; url_oss << model_name; Log(out_, "Model will be saved to {}\n", fs_path.lexically_normal().string()); - std::string py_stdout, py_stderr; + auto out_cb = [&](const std::string& out, const std::string& err) { + Log(out_, out); + Log(out_, err); + }; + auto in_cb = [&](std::string& in) {}; + auto run_cb = [&]() -> bool { + return run_transcription_; + }; bool ret = PythonWrapper::InvokeWithArgs({ "-u", // Unbuffered output "-m wget", url_oss.str(), "-o", fs_path.string(), - }, &py_stdout, &py_stderr); - Log(out_, py_stdout); - Log(out_, py_stderr); + }, std::move(out_cb), std::move(in_cb), std::move(run_cb)); if (!ret) { Log(out_, "Failed to download model!\n"); return false; @@ -260,13 +268,17 @@ void WhisperCPP::Start(const AppConfig& c) { ScopeGuard mic_stream_cleanup([mic_stream]() { mic_stream->Release(); }); { - std::function out_cb = - [&](const std::string& out, const std::string& err) -> void { + auto out_cb = [&](const std::string& out, const std::string& err) -> void { Log(out_, out); Log(out_, err); }; + auto in_cb = [&](std::string& in) {}; + auto run_cb = [&]() -> bool { + return run_transcription_; + }; Log(out_, "Installing pip\n"); - if (!PythonWrapper::InstallPip(std::move(out_cb))) { + if (!PythonWrapper::InstallPip(std::move(out_cb), std::move(in_cb), + std::move(run_cb))) { Log(out_, "Failed to install pip!\n"); return; } @@ -327,6 +339,7 @@ void WhisperCPP::Start(const AppConfig& c) { // entries (source: I heard it from someone once). static const std::vector banned_words{ " -", + " (static)", }; const sSegment* const segments = results->getSegments(); @@ -518,11 +531,11 @@ void WhisperCPP::StopCustomChatbox() { Log(out_, "Done!\n"); } -bool WhisperCPP::GetMicsImpl(std::vector& mics) { +bool WhisperCPP::GetMicsImpl(std::vector>& mics) { pfnFoundCaptureDevices dev_cb = [](int len, const sCaptureDevice* buf, void* pv)->HRESULT __stdcall { - std::vector* mics = static_cast*>(pv); + auto mics = static_cast>*>(pv); for (int i = 0; i < len; i++) { - mics->push_back(buf[i]); + mics->push_back(std::make_unique(buf[i])); } return S_OK; }; diff --git a/GUI/GUI/GUI/WhisperCPP.h b/GUI/GUI/GUI/WhisperCPP.h index 1390e97..7b3f17d 100644 --- a/GUI/GUI/GUI/WhisperCPP.h +++ b/GUI/GUI/GUI/WhisperCPP.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -45,7 +46,8 @@ public: void StopCustomChatbox(); private: - bool GetMicsImpl(std::vector& mics); + bool GetMicsImpl( + std::vector>& mics); wxTextCtrl* out_; Whisper::iMediaFoundation* f_; -- cgit v1.2.3