From 084d775c3e63da9f6da4018c79ce649fb04150a2 Mon Sep 17 00:00:00 2001 From: Kodai Aoyama Date: Tue, 21 May 2024 22:46:28 +0900 Subject: [PATCH 1/2] backend logic except downloading --- src-tauri/Cargo.lock | 446 +++++++++++++++++++++++-- src-tauri/Cargo.toml | 1 + src-tauri/src/main.rs | 9 + src-tauri/src/module/mod.rs | 1 + src-tauri/src/module/record.rs | 13 +- src-tauri/src/module/record_desktop.rs | 13 +- src-tauri/src/module/translation_ja.rs | 209 ++++++++++++ 7 files changed, 654 insertions(+), 38 deletions(-) create mode 100644 src-tauri/src/module/translation_ja.rs diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 2a717db..fad4a44 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -105,9 +105,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.81" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" +checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" [[package]] name = "arbitrary" @@ -143,7 +143,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.61", ] [[package]] @@ -285,7 +285,7 @@ checksum = "30c5ef0ede93efbf733c1a727f3b6b5a1060bbedd5600183e66f6e4be4af0ec5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.61", ] [[package]] @@ -320,7 +320,7 @@ checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.61", ] [[package]] @@ -448,7 +448,7 @@ dependencies = [ "bitflags 2.5.0", "cexpr", "clang-sys", - "itertools", + "itertools 0.12.1", "lazy_static", "lazycell", "log", @@ -458,7 +458,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.55", + "syn 2.0.61", "which", ] @@ -759,6 +759,16 @@ dependencies = [ "objc", ] +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "color_quant" version = "1.1.0" @@ -784,6 +794,19 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "console" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys 0.52.0", +] + [[package]] name = "const-oid" version = "0.9.6" @@ -1008,7 +1031,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.55", + "syn 2.0.61", +] + +[[package]] +name = "ct2rs" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a02ec8476ffc2a7330384ae07bc69e05d3a9366167e6479d9b827818e677977e" +dependencies = [ + "anyhow", + "cmake", + "cxx", + "cxx-build", + "sentencepiece", + "tokenizers", + "walkdir", ] [[package]] @@ -1018,7 +1056,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad291aa74992b9b7a7e88c38acbbf6ad7e107f1d90ee8775b7bc1fc3394f485c" dependencies = [ "quote", - "syn 2.0.55", + "syn 2.0.61", +] + +[[package]] +name = "cxx" +version = "1.0.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb497fad022245b29c2a0351df572e2d67c1046bcef2260ebc022aec81efea82" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9327c7f9fbd6329a200a5d4aa6f674c60ab256525ff0084b52a889d4e4c60cee" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn 2.0.61", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "688c799a4a846f1c0acb9f36bb9c6272d9b3d9457f3633c7753c6057270df13c" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928bc249a7e3cd554fd2e8e08a426e9670c50bbfc9a621653cfa9accc9641783" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", ] [[package]] @@ -1042,7 +1124,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.55", + "syn 2.0.61", ] [[package]] @@ -1053,7 +1135,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core", "quote", - "syn 2.0.55", + "syn 2.0.61", ] [[package]] @@ -1226,7 +1308,38 @@ checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.61", +] + +[[package]] +name = "derive_builder" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0350b5cb0331628a5916d6c5c0b72e97393b8b6b03b47a9284f4e7f5a405ffd7" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d48cda787f839151732d396ac69e3473923d54312c070ee21e9effcaa8ca0b1d" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" +dependencies = [ + "derive_builder_core", + "syn 2.0.61", ] [[package]] @@ -1358,6 +1471,12 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "encoding_rs" version = "0.8.33" @@ -1385,7 +1504,7 @@ checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.61", ] [[package]] @@ -1410,6 +1529,15 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0474425d51df81997e2f90a21591180b38eccf27292d755f3e30750225c175b" +[[package]] +name = "esaxx-rs" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d817e038c30374a4bcb22f94d0a8a0e216958d4c3dcde369b1439fec4bdda6e6" +dependencies = [ + "cc", +] + [[package]] name = "etcetera" version = "0.8.0" @@ -1620,7 +1748,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.61", ] [[package]] @@ -1740,7 +1868,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.61", ] [[package]] @@ -2452,6 +2580,19 @@ dependencies = [ "serde", ] +[[package]] +name = "indicatif" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" +dependencies = [ + "console", + "instant", + "number_prefix", + "portable-atomic", + "unicode-width", +] + [[package]] name = "infer" version = "0.13.0" @@ -2478,7 +2619,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.61", ] [[package]] @@ -2498,6 +2639,24 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.12.1" @@ -2726,6 +2885,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd1bc4d24ad230d21fb898d1116b1801d7adfc449d42026475862ab48b11e70e" +[[package]] +name = "link-cplusplus" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d240c6f7e1ba3a28b0249f774e6a9dd0175054b52dfbb61b16eb8505c3785c9" +dependencies = [ + "cc", +] + [[package]] name = "linux-raw-sys" version = "0.3.8" @@ -2786,6 +2954,7 @@ dependencies = [ "core-graphics 0.23.1", "cpal", "crossbeam-channel", + "ct2rs", "dasp", "futures-util", "hound", @@ -2850,6 +3019,22 @@ dependencies = [ "core-foundation-sys", ] +[[package]] +name = "macro_rules_attribute" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a82271f7bc033d84bbca59a3ce3e4159938cb08a9c3aebbe54d215131518a13" +dependencies = [ + "macro_rules_attribute-proc_macro", + "paste", +] + +[[package]] +name = "macro_rules_attribute-proc_macro" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dd856d451cc0da70e2ef2ce95a18e39a93b7558bedf10201ad28503f918568" + [[package]] name = "malloc_buf" version = "0.0.6" @@ -2984,6 +3169,27 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "monostate" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d208407d7552cd041d8cdb69a1bc3303e029c598738177a3d87082004dc0e1e" +dependencies = [ + "monostate-impl", + "serde", +] + +[[package]] +name = "monostate-impl" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7ce64b975ed4f123575d11afd9491f2e37bbd5813fbfbc0f09ae1fbddea74e0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + [[package]] name = "native-tls" version = "0.2.11" @@ -3203,7 +3409,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.61", ] [[package]] @@ -3279,6 +3485,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + [[package]] name = "objc" version = "0.2.7" @@ -3356,6 +3568,28 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "onig" +version = "6.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c4b31c8722ad9171c6d77d3557db078cab2bd50afcc9d09c8b315c59df8ca4f" +dependencies = [ + "bitflags 1.3.2", + "libc", + "once_cell", + "onig_sys", +] + +[[package]] +name = "onig_sys" +version = "69.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b829e3d7e9cc74c7e315ee8edb185bf4190da5acde74afd7fc59c35b1f086e7" +dependencies = [ + "cc", + "pkg-config", +] + [[package]] name = "open" version = "3.2.0" @@ -3389,7 +3623,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.61", ] [[package]] @@ -3642,7 +3876,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.61", ] [[package]] @@ -3780,6 +4014,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "portable-atomic" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" + [[package]] name = "powerfmt" version = "0.2.0" @@ -3805,7 +4045,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d3928fb5db768cb86f891ff014f0144589297e3c6a1aba6ed7cecfdace270c7" dependencies = [ "proc-macro2", - "syn 2.0.55", + "syn 2.0.61", ] [[package]] @@ -3850,9 +4090,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" dependencies = [ "unicode-ident", ] @@ -3873,7 +4113,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd" dependencies = [ "quote", - "syn 2.0.55", + "syn 2.0.61", +] + +[[package]] +name = "prost" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +dependencies = [ + "anyhow", + "itertools 0.10.5", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] @@ -4013,7 +4276,7 @@ dependencies = [ "built", "cfg-if", "interpolate_name", - "itertools", + "itertools 0.12.1", "libc", "libfuzzer-sys", "log", @@ -4065,6 +4328,17 @@ dependencies = [ "rayon-core", ] +[[package]] +name = "rayon-cond" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "059f538b55efd2309c9794130bc149c6a553db90e9d99c2030785c82f0bd7df9" +dependencies = [ + "either", + "itertools 0.11.0", + "rayon", +] + [[package]] name = "rayon-core" version = "1.12.1" @@ -4366,6 +4640,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scratch" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3cf7c11c38cb994f3d40e8a8cde3bbd1f72a435e4c49e85d6553d8312306152" + [[package]] name = "screencapturekit" version = "0.2.7" @@ -4454,6 +4734,32 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +[[package]] +name = "sentencepiece" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ae716e54c860d65df824a5b606b464e8f2acfc4a7fe93b2a1f6b9a173d1fff5" +dependencies = [ + "libc", + "num-derive 0.3.3", + "num-traits", + "prost", + "prost-derive", + "sentencepiece-sys", + "thiserror", +] + +[[package]] +name = "sentencepiece-sys" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f21c66315e346665798e116d1c21201434715e13dd691f3f33f6276746d0b71f" +dependencies = [ + "cc", + "cmake", + "pkg-config", +] + [[package]] name = "serde" version = "1.0.197" @@ -4471,7 +4777,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.61", ] [[package]] @@ -4494,7 +4800,7 @@ checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.61", ] [[package]] @@ -4545,7 +4851,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.61", ] [[package]] @@ -4770,13 +5076,25 @@ dependencies = [ "der", ] +[[package]] +name = "spm_precompiled" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5851699c4033c63636f7ea4cf7b7c1f1bf06d0cc03cfb42e711de5a5c46cf326" +dependencies = [ + "base64 0.13.1", + "nom", + "serde", + "unicode-segmentation", +] + [[package]] name = "sqlformat" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c" dependencies = [ - "itertools", + "itertools 0.12.1", "nom", "unicode_categories", ] @@ -5111,9 +5429,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.55" +version = "2.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0" +checksum = "c993ed8ccba56ae856363b1845da7266a7cb78e1d146c8a32d54b45a8b831fc9" dependencies = [ "proc-macro2", "quote", @@ -5538,6 +5856,15 @@ dependencies = [ "utf-8", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "thin-slice" version = "0.1.1" @@ -5561,7 +5888,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.61", ] [[package]] @@ -5631,6 +5958,38 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "tokenizers" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e500fad1dd3af3d626327e6a3fe5050e664a6eaa4708b8ca92f1794aaf73e6fd" +dependencies = [ + "aho-corasick", + "derive_builder", + "esaxx-rs", + "getrandom 0.2.12", + "indicatif", + "itertools 0.12.1", + "lazy_static", + "log", + "macro_rules_attribute", + "monostate", + "onig", + "paste", + "rand 0.8.5", + "rayon", + "rayon-cond", + "regex", + "regex-syntax 0.8.2", + "serde", + "serde_json", + "spm_precompiled", + "thiserror", + "unicode-normalization-alignments", + "unicode-segmentation", + "unicode_categories", +] + [[package]] name = "tokio" version = "1.36.0" @@ -5658,7 +6017,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.61", ] [[package]] @@ -5790,7 +6149,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.61", ] [[package]] @@ -5908,12 +6267,27 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-normalization-alignments" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43f613e4fa046e69818dd287fdc4bc78175ff20331479dab6e1b0f98d57062de" +dependencies = [ + "smallvec", +] + [[package]] name = "unicode-segmentation" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +[[package]] +name = "unicode-width" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" + [[package]] name = "unicode_categories" version = "0.1.1" @@ -6095,7 +6469,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.61", "wasm-bindgen-shared", ] @@ -6129,7 +6503,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.61", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -7092,7 +7466,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.61", ] [[package]] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 287461f..b3900cd 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -43,6 +43,7 @@ core-graphics = "0.23.1" objc = "0.2" objc-foundation = "0.1" objc_id = "0.1" +ct2rs = {version = "0.7.3", features = ["accelerate"] } [target.'cfg(target_arch = "x86_64")'.dependencies] whisper-rs = { version = "0.11.1", features = ["metal"] } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 9fa75c9..e463721 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -35,6 +35,7 @@ use module::{ screenshot::{self, AppWindow}, transcription::{TraceCompletion, Transcription}, transcription_online::TranscriptionOnline, + translation_ja::TranslationJa, }; struct RecordState(Arc>>>); @@ -192,6 +193,14 @@ fn start_trace_command( } else if transcription_accuracy.starts_with("online-chat") { let mut chat_online = ChatOnline::new(window.app_handle(), speaker_language, note_id); chat_online.start(stop_convert_rx, true); + } else if transcription_accuracy.starts_with("translataion-ja") { + let mut translation_ja = TranslationJa::new( + window.app_handle(), + transcription_accuracy, + speaker_language, + note_id, + ); + translation_ja.start(stop_convert_rx, true); } else { let mut transcription = Transcription::new( window.app_handle(), diff --git a/src-tauri/src/module/mod.rs b/src-tauri/src/module/mod.rs index 11a2804..61e915c 100644 --- a/src-tauri/src/module/mod.rs +++ b/src-tauri/src/module/mod.rs @@ -12,5 +12,6 @@ mod sqlite; mod transcriber; pub mod transcription; pub mod transcription_online; +pub mod translation_ja; mod writer; pub mod screenshot; \ No newline at end of file diff --git a/src-tauri/src/module/record.rs b/src-tauri/src/module/record.rs index e066756..5862dc4 100644 --- a/src-tauri/src/module/record.rs +++ b/src-tauri/src/module/record.rs @@ -24,7 +24,7 @@ use tauri::{api::path::data_dir, AppHandle, Manager}; use super::{ chat_online, recognizer::MyRecognizer, sqlite::Sqlite, transcription, transcription_online, - writer::Writer, + translation_ja, writer::Writer, }; pub struct Record { @@ -208,6 +208,17 @@ impl Record { if let Some(singleton) = lock.as_mut() { singleton.start(stop_convert_rx_clone, false); } + } else if transcription_accuracy_clone.starts_with("translataion-ja") { + translation_ja::initialize_translation_ja( + app_handle_clone, + transcription_accuracy_clone, + speaker_language_clone, + note_id, + ); + let mut lock = translation_ja::SINGLETON_INSTANCE.lock().unwrap(); + if let Some(singleton) = lock.as_mut() { + singleton.start(stop_convert_rx_clone, false); + } } else { transcription::initialize_transcription( app_handle_clone, diff --git a/src-tauri/src/module/record_desktop.rs b/src-tauri/src/module/record_desktop.rs index 81ea45a..b6312e6 100644 --- a/src-tauri/src/module/record_desktop.rs +++ b/src-tauri/src/module/record_desktop.rs @@ -39,7 +39,7 @@ use vosk::Recognizer; use super::{ chat_online, recognizer::MyRecognizer, sqlite::Sqlite, transcription, transcription_online, - writer::Writer, + translation_ja, writer::Writer, }; pub struct RecordDesktop { @@ -240,6 +240,17 @@ impl RecordDesktop { if let Some(singleton) = lock.as_mut() { singleton.start(stop_convert_rx_clone, false); } + } else if transcription_accuracy_clone.starts_with("translataion-ja") { + translation_ja::initialize_translation_ja( + app_handle_clone, + transcription_accuracy_clone, + speaker_language_clone, + note_id, + ); + let mut lock = translation_ja::SINGLETON_INSTANCE.lock().unwrap(); + if let Some(singleton) = lock.as_mut() { + singleton.start(stop_convert_rx_clone, false); + } } else { transcription::initialize_transcription( app_handle_clone, diff --git a/src-tauri/src/module/translation_ja.rs b/src-tauri/src/module/translation_ja.rs new file mode 100644 index 0000000..70f51bf --- /dev/null +++ b/src-tauri/src/module/translation_ja.rs @@ -0,0 +1,209 @@ +use super::{sqlite::Sqlite, transcriber::Transcriber}; + +use crossbeam_channel::Receiver; +use ct2rs::{config::Config, sentencepiece::Tokenizer, TranslationOptions, Translator}; +use hound::SampleFormat; +use samplerate_rs::{convert, ConverterType}; +use std::sync::Mutex; +use tauri::{AppHandle, Manager}; +use whisper_rs::WhisperContext; + +#[derive(Debug, Clone, serde::Serialize)] +pub struct TraceCompletion {} + +pub struct TranslationJa { + app_handle: AppHandle, + sqlite: Sqlite, + ctx: WhisperContext, + translator: Translator, + speaker_language: String, + transcription_accuracy: String, // suffix should be "en" on transcriber translatoin process + note_id: u64, +} + +impl TranslationJa { + pub fn new( + app_handle: AppHandle, + transcription_accuracy: String, + speaker_language: String, + note_id: u64, + ) -> Self { + let app_handle_clone = app_handle.clone(); + let model_path = app_handle + .path_resolver() + .resolve_resource(format!("resources/fugumt/fugumt-en-ja")) + .unwrap() + .to_string_lossy() + .to_string(); + + TranslationJa { + app_handle, + sqlite: Sqlite::new(), + ctx: Transcriber::build(app_handle_clone, transcription_accuracy.clone()), + translator: Translator::new( + &model_path, + Tokenizer::new(&model_path).unwrap(), + &Config::default(), + ).unwrap(), + speaker_language, + transcription_accuracy, + note_id, + } + } + + pub fn start(&mut self, stop_convert_rx: Receiver<()>, is_continuous: bool) { + while Self::convert(self).is_ok() { + if is_continuous { + let vosk_speech = self.sqlite.select_vosk(self.note_id); + if vosk_speech.is_err() { + self.app_handle + .clone() + .emit_all("traceCompletion", TraceCompletion {}) + .unwrap(); + break; + } + } + if stop_convert_rx.try_recv().is_ok() { + let vosk_speech = self.sqlite.select_vosk(self.note_id); + if vosk_speech.is_err() { + self.app_handle + .clone() + .emit_all("traceCompletion", TraceCompletion {}) + .unwrap(); + } else { + self.app_handle + .clone() + .emit_all("traceUnCompletion", TraceCompletion {}) + .unwrap(); + } + break; + } + } + } + + fn convert(&mut self) -> Result<(), rusqlite::Error> { + let vosk_speech = self.sqlite.select_vosk(self.note_id); + return vosk_speech.and_then(|speech| { + let mut reader = hound::WavReader::open(speech.wav).unwrap(); + + let spec = reader.spec(); + let mut data = + Vec::with_capacity((spec.channels as usize) * (reader.duration() as usize)); + match (spec.bits_per_sample, spec.sample_format) { + (16, SampleFormat::Int) => { + for sample in reader.samples::() { + data.push((sample.unwrap() as f32) / (0x7fffi32 as f32)); + } + } + (24, SampleFormat::Int) => { + for sample in reader.samples::() { + let val = (sample.unwrap() as f32) / (0x00ff_ffffi32 as f32); + data.push(val); + } + } + (32, SampleFormat::Int) => { + for sample in reader.samples::() { + data.push((sample.unwrap() as f32) / (0x7fff_ffffi32 as f32)); + } + } + (32, SampleFormat::Float) => { + for sample in reader.samples::() { + data.push(sample.unwrap()); + } + } + _ => panic!( + "Tried to read file but there was a problem: {:?}", + hound::Error::Unsupported + ), + } + let data = if spec.channels != 1 { + whisper_rs::convert_stereo_to_mono_audio(&data).unwrap() + } else { + data + }; + let audio_data = convert( + spec.sample_rate, + 16000, + 1, + ConverterType::SincBestQuality, + &data, + ) + .unwrap(); + + let mut state = self.ctx.create_state().expect("failed to create state"); + let result = state.full( + Transcriber::build_params( + self.speaker_language.clone(), + self.transcription_accuracy.clone(), + ), + &audio_data[..], + ); + if result.is_ok() { + let num_segments = state + .full_n_segments() + .expect("failed to get number of segments"); + let mut converted: Vec = vec!["".to_string()]; + for i in 0..num_segments { + let segment = state.full_get_segment_text(i); + if segment.is_ok() { + converted.push(segment.unwrap().to_string()); + }; + } + + let result_on_whisper = converted.join(""); + let sources: Vec = result_on_whisper.lines().map(String::from).collect(); + let res = self.translator.translate_batch( + &sources, + &TranslationOptions { + beam_size: 5, + ..Default::default() + }, + )?; + let mut translated: Vec = vec!["".to_string()]; + for (r, _) in res { + translated.push(r); + } + + let updated = self + .sqlite + .update_model_vosk_to_whisper(speech.id, translated.join("")); + + let updated = updated.unwrap(); + if updated.content != "" { + self.app_handle + .clone() + .emit_all("finalTextConverted", updated) + .unwrap(); + } + } else { + println!("whisper is temporally failed, so skipping...") + } + + Ok(()) + }); + } +} + +pub static SINGLETON_INSTANCE: Mutex> = Mutex::new(None); + +pub fn initialize_translation_ja( + app_handle: AppHandle, + transcription_accuracy: String, + speaker_language: String, + note_id: u64, +) { + let mut singleton = SINGLETON_INSTANCE.lock().unwrap(); + if singleton.is_none() { + *singleton = Some(TranslationJa::new( + app_handle, + transcription_accuracy, + speaker_language, + note_id, + )); + } +} + +pub fn drop_translation_ja() { + let mut singleton = SINGLETON_INSTANCE.lock().unwrap(); + *singleton = None; +} From e16d92a2910608f959ddb7c03142f96f2093254a Mon Sep 17 00:00:00 2001 From: Kodai Aoyama Date: Sat, 25 May 2024 17:00:01 +0900 Subject: [PATCH 2/2] frontend logic & backend download feature --- src-tauri/migrations/001.sql | 4 +- src-tauri/src/main.rs | 24 ++-- src-tauri/src/module/downloader/fugumt.rs | 119 ++++++++++++++++++ src-tauri/src/module/downloader/mod.rs | 1 + src-tauri/src/module/record.rs | 3 +- src-tauri/src/module/record_desktop.rs | 3 +- src-tauri/src/module/translation_ja.rs | 15 +-- .../molecules/ModelDownloadFugumtButton.tsx | 27 ++++ .../molecules/ModelDownloadFugumtProgress.tsx | 42 +++++++ .../molecules/TranscriptionAccuracy.tsx | 32 ++++- src/components/organisms/SettingsMain.tsx | 12 ++ src/store/atoms/modelFugumtDownloadedState.ts | 22 ++++ .../atoms/modelFugumtDownloadingState.ts | 6 + 13 files changed, 281 insertions(+), 29 deletions(-) create mode 100644 src-tauri/src/module/downloader/fugumt.rs create mode 100644 src/components/molecules/ModelDownloadFugumtButton.tsx create mode 100644 src/components/molecules/ModelDownloadFugumtProgress.tsx create mode 100644 src/store/atoms/modelFugumtDownloadedState.ts create mode 100644 src/store/atoms/modelFugumtDownloadingState.ts diff --git a/src-tauri/migrations/001.sql b/src-tauri/migrations/001.sql index 58bb9f3..78f99c7 100644 --- a/src-tauri/migrations/001.sql +++ b/src-tauri/migrations/001.sql @@ -141,4 +141,6 @@ VALUES("small-hi-0.22", "vosk"); INSERT INTO models(model_name, model_type) VALUES("small-cs-0.4-rhasspy", "vosk"); INSERT INTO models(model_name, model_type) -VALUES("small-pl-0.22", "vosk"); \ No newline at end of file +VALUES("small-pl-0.22", "vosk"); +INSERT INTO models(model_name, model_type) +VALUES("fugumt-en-ja", "fugumt"); \ No newline at end of file diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 1e54d39..bdfa6f3 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -26,7 +26,9 @@ use module::{ chat_online::ChatOnline, deleter::NoteDeleter, device::{self, Device}, - downloader::{vosk::VoskModelDownloader, whisper::WhisperModelDownloader}, + downloader::{ + fugumt::FugumtModelDownloader, vosk::VoskModelDownloader, whisper::WhisperModelDownloader, + }, model_type_vosk::ModelTypeVosk, model_type_whisper::ModelTypeWhisper, permissions, @@ -34,9 +36,9 @@ use module::{ record_desktop::RecordDesktop, screenshot::{self, AppWindow}, transcription::{TraceCompletion, Transcription}, + transcription_amivoice::TranscriptionAmivoice, transcription_online::TranscriptionOnline, translation_ja::TranslationJa, - transcription_amivoice::TranscriptionAmivoice, }; struct RecordState(Arc>>>); @@ -67,6 +69,14 @@ fn download_vosk_model_command(window: Window, model: String) { }); } +#[tauri::command] +fn download_fugumt_model_command(window: Window) { + std::thread::spawn(move || { + let dl = FugumtModelDownloader::new(window.app_handle().clone()); + dl.download() + }); +} + #[tauri::command] fn list_devices_command() -> Vec { device::list_devices() @@ -192,18 +202,15 @@ fn start_trace_command( ); transcription_online.start(stop_convert_rx, true); } else if transcription_accuracy.starts_with("online-amivoice") { - let mut transcription_amivoice = TranscriptionAmivoice::new( - window.app_handle(), - note_id, - ); + let mut transcription_amivoice = + TranscriptionAmivoice::new(window.app_handle(), note_id); transcription_amivoice.start(stop_convert_rx, true); } else if transcription_accuracy.starts_with("online-chat") { let mut chat_online = ChatOnline::new(window.app_handle(), speaker_language, note_id); chat_online.start(stop_convert_rx, true); - } else if transcription_accuracy.starts_with("translataion-ja") { + } else if transcription_accuracy.starts_with("fugumt-en-ja") { let mut translation_ja = TranslationJa::new( window.app_handle(), - transcription_accuracy, speaker_language, note_id, ); @@ -316,6 +323,7 @@ fn main() { delete_note_command, download_whisper_model_command, download_vosk_model_command, + download_fugumt_model_command, list_devices_command, list_apps_command, list_app_windows_command, diff --git a/src-tauri/src/module/downloader/fugumt.rs b/src-tauri/src/module/downloader/fugumt.rs new file mode 100644 index 0000000..5df67aa --- /dev/null +++ b/src-tauri/src/module/downloader/fugumt.rs @@ -0,0 +1,119 @@ +use tauri::{AppHandle, Manager}; + +use futures_util::StreamExt; +use std::cmp::min; +use std::fs::File; +use std::io::Write; + +use crate::module::sqlite::Sqlite; + +#[derive(Debug, Clone, serde::Serialize)] +pub struct Progress { + pub model_type: String, + pub rate: f64, + pub is_progress: bool, +} + +pub struct FugumtModelDownloader { + app_handle: AppHandle, +} +impl FugumtModelDownloader { + pub fn new(app_handle: AppHandle) -> Self { + Self { app_handle } + } + + #[tokio::main] + pub async fn download(&self) { + let model_type = "fugumt-en-ja"; + let path: &str = &self + .app_handle + .path_resolver() + .resolve_resource("resources/fugumt-en-ja.zip") + .unwrap() + .to_string_lossy() + .to_string(); + let url = "https://object-storage.tyo1.conoha.io/v1/nc_b22de95e3cf1434da07499038766e2b7/lycoris/fugumt-en-ja.zip"; + let res = reqwest::get(url).await.unwrap(); + let total_size = res + .content_length() + .ok_or(format!("Failed to get content length from '{}'", url)) + .unwrap(); + + let _ = &self.app_handle.emit_all( + "downloadFugumtProgress", + Progress { + model_type: model_type.to_string(), + rate: 0.0, + is_progress: true, + }, + ); + + let mut file; + let mut downloaded: u64 = 0; + let mut stream = res.bytes_stream(); + + println!("Seeking in file."); + if std::path::Path::new(&path).exists() { + println!("File exists. Removig..."); + let _ = std::fs::remove_file(&path); + } + file = File::create(&path) + .or(Err(format!("Failed to create file '{}'", &path))) + .unwrap(); + + println!("Commencing transfer"); + let mut rate = 0.0; + while let Some(item) = stream.next().await { + let chunk = item + .or(Err(format!("Error while downloading file"))) + .unwrap(); + file.write(&chunk) + .or(Err(format!("Error while writing to file"))) + .unwrap(); + let new = min(downloaded + (chunk.len() as u64), total_size); + downloaded = new; + + let current_rate = ((new as f64 * 100.0) / total_size as f64).round(); + if rate != current_rate { + let _ = &self.app_handle.emit_all( + "downloadFugumtProgress", + Progress { + model_type: model_type.to_string(), + rate: current_rate, + is_progress: true, + }, + ); + rate = current_rate + } + } + + let dir: &str = &self + .app_handle + .path_resolver() + .resolve_resource("resources") + .unwrap() + .to_string_lossy() + .to_string(); + let _ = std::process::Command::new("sh") + .arg("-c") + .arg(format!("unzip {} -d {}", path, dir)) + .output() + .expect("failed"); + let _ = std::process::Command::new("sh") + .arg("-c") + .arg(format!("rm {}", path)) + .output() + .expect("failed"); + + let _ = Sqlite::new().update_model_is_downloaded(model_type.to_string(), 1); + + let _ = &self.app_handle.emit_all( + "downloadFugumtProgress", + Progress { + model_type: model_type.to_string(), + rate: 0.0, + is_progress: false, + }, + ); + } +} diff --git a/src-tauri/src/module/downloader/mod.rs b/src-tauri/src/module/downloader/mod.rs index 4048d87..1018dfc 100644 --- a/src-tauri/src/module/downloader/mod.rs +++ b/src-tauri/src/module/downloader/mod.rs @@ -1,2 +1,3 @@ pub mod whisper; pub mod vosk; +pub mod fugumt; \ No newline at end of file diff --git a/src-tauri/src/module/record.rs b/src-tauri/src/module/record.rs index 5d99cfd..6cbd24a 100644 --- a/src-tauri/src/module/record.rs +++ b/src-tauri/src/module/record.rs @@ -218,10 +218,9 @@ impl Record { if let Some(singleton) = lock.as_mut() { singleton.start(stop_convert_rx_clone, false); } - } else if transcription_accuracy_clone.starts_with("translataion-ja") { + } else if transcription_accuracy_clone.starts_with("fugumt-en-ja") { translation_ja::initialize_translation_ja( app_handle_clone, - transcription_accuracy_clone, speaker_language_clone, note_id, ); diff --git a/src-tauri/src/module/record_desktop.rs b/src-tauri/src/module/record_desktop.rs index c69c279..0ac58c3 100644 --- a/src-tauri/src/module/record_desktop.rs +++ b/src-tauri/src/module/record_desktop.rs @@ -250,10 +250,9 @@ impl RecordDesktop { if let Some(singleton) = lock.as_mut() { singleton.start(stop_convert_rx_clone, false); } - } else if transcription_accuracy_clone.starts_with("translataion-ja") { + } else if transcription_accuracy_clone.starts_with("fugumt-en-ja") { translation_ja::initialize_translation_ja( app_handle_clone, - transcription_accuracy_clone, speaker_language_clone, note_id, ); diff --git a/src-tauri/src/module/translation_ja.rs b/src-tauri/src/module/translation_ja.rs index 70f51bf..fbf7297 100644 --- a/src-tauri/src/module/translation_ja.rs +++ b/src-tauri/src/module/translation_ja.rs @@ -17,21 +17,19 @@ pub struct TranslationJa { ctx: WhisperContext, translator: Translator, speaker_language: String, - transcription_accuracy: String, // suffix should be "en" on transcriber translatoin process note_id: u64, } impl TranslationJa { pub fn new( app_handle: AppHandle, - transcription_accuracy: String, speaker_language: String, note_id: u64, ) -> Self { let app_handle_clone = app_handle.clone(); let model_path = app_handle .path_resolver() - .resolve_resource(format!("resources/fugumt/fugumt-en-ja")) + .resolve_resource(format!("resources/fugumt-en-ja")) .unwrap() .to_string_lossy() .to_string(); @@ -39,14 +37,13 @@ impl TranslationJa { TranslationJa { app_handle, sqlite: Sqlite::new(), - ctx: Transcriber::build(app_handle_clone, transcription_accuracy.clone()), + ctx: Transcriber::build(app_handle_clone, "large-translate-to-en".to_string()), translator: Translator::new( &model_path, Tokenizer::new(&model_path).unwrap(), &Config::default(), ).unwrap(), speaker_language, - transcription_accuracy, note_id, } } @@ -134,7 +131,7 @@ impl TranslationJa { let result = state.full( Transcriber::build_params( self.speaker_language.clone(), - self.transcription_accuracy.clone(), + "large-translate-to-en".to_string(), ), &audio_data[..], ); @@ -152,13 +149,13 @@ impl TranslationJa { let result_on_whisper = converted.join(""); let sources: Vec = result_on_whisper.lines().map(String::from).collect(); - let res = self.translator.translate_batch( + let res: Vec<(String, Option)> = self.translator.translate_batch( &sources, &TranslationOptions { beam_size: 5, ..Default::default() }, - )?; + ).unwrap(); let mut translated: Vec = vec!["".to_string()]; for (r, _) in res { translated.push(r); @@ -188,7 +185,6 @@ pub static SINGLETON_INSTANCE: Mutex> = Mutex::new(None); pub fn initialize_translation_ja( app_handle: AppHandle, - transcription_accuracy: String, speaker_language: String, note_id: u64, ) { @@ -196,7 +192,6 @@ pub fn initialize_translation_ja( if singleton.is_none() { *singleton = Some(TranslationJa::new( app_handle, - transcription_accuracy, speaker_language, note_id, )); diff --git a/src/components/molecules/ModelDownloadFugumtButton.tsx b/src/components/molecules/ModelDownloadFugumtButton.tsx new file mode 100644 index 0000000..50bc0b2 --- /dev/null +++ b/src/components/molecules/ModelDownloadFugumtButton.tsx @@ -0,0 +1,27 @@ +import { invoke } from '@tauri-apps/api/tauri' +import { useRecoilState, useRecoilValue } from 'recoil' +import { modelFugumtDownloadingState } from '../../store/atoms/modelFugumtDownloadingState' +import { modelFugumtDownloadedState } from '../../store/atoms/modelFugumtDownloadedState' + +const ModelDownloadFugumtButton = (): JSX.Element => { + const modelType = "fugumt-en-ja" + const downloadedModels = useRecoilValue(modelFugumtDownloadedState) + const [downloadingModels, setDownloadingModels] = useRecoilState(modelFugumtDownloadingState) + const click = () => { + setDownloadingModels([...downloadingModels, modelType]) + invoke('download_fugumt_model_command') + } + const is_downloaded = downloadedModels.filter(m => m === modelType).length > 0 + const is_downloading = downloadingModels.filter(m => m === modelType).length > 0 + + return ( + + ) +} + +export { ModelDownloadFugumtButton } \ No newline at end of file diff --git a/src/components/molecules/ModelDownloadFugumtProgress.tsx b/src/components/molecules/ModelDownloadFugumtProgress.tsx new file mode 100644 index 0000000..5b1a6bc --- /dev/null +++ b/src/components/molecules/ModelDownloadFugumtProgress.tsx @@ -0,0 +1,42 @@ +import { useRecoilState, useSetRecoilState } from 'recoil' +import { modelFugumtDownloadingState } from '../../store/atoms/modelFugumtDownloadingState' +import { listen } from '@tauri-apps/api/event' +import { useEffect, useState } from 'react' +import { ProgressType } from '../../type/progress.type' +import { modelFugumtDownloadedState } from '../../store/atoms/modelFugumtDownloadedState' + +const ModelDownloadFugumtProgress = (): JSX.Element => { + const modelType = "fugumt-en-ja" + const setDownloadedModel = useSetRecoilState(modelFugumtDownloadedState) + const [downloadingModels, setDownloadingModels] = useRecoilState(modelFugumtDownloadingState) + const [progress, setProgress] = useState({ + model_type: modelType, + rate: 0, + is_progress: false + }) + useEffect(() => { + const unlisten = listen('downloadFugumtProgress', event => { + const p = event.payload as ProgressType + if (p.model_type === modelType) { + setProgress(p) + if (!p.is_progress) { + setDownloadingModels(prev => prev.filter(m => m !== modelType)) + setDownloadedModel(prev => [...prev, modelType]) + } + } + }) + return () => { + unlisten.then(f => f()); + } + }, []) + if (downloadingModels.filter(m => m === modelType).length > 0) { + return ( +
+
{progress.rate}%
+
+ ) + } + return (<>) +} + +export { ModelDownloadFugumtProgress } \ No newline at end of file diff --git a/src/components/molecules/TranscriptionAccuracy.tsx b/src/components/molecules/TranscriptionAccuracy.tsx index 62e4360..2feb41e 100644 --- a/src/components/molecules/TranscriptionAccuracy.tsx +++ b/src/components/molecules/TranscriptionAccuracy.tsx @@ -6,9 +6,11 @@ import { recordState } from "../../store/atoms/recordState"; import { speakerLanguageState } from "../../store/atoms/speakerLanguageState"; import { settingKeyState } from "../../store/atoms/settingKeyState"; import { tracingState } from "../../store/atoms/tracingState"; +import { modelFugumtDownloadedState } from "../../store/atoms/modelFugumtDownloadedState"; const TranscriptionAccuracy = (): JSX.Element => { const downloadedModels = useRecoilValue(modelWhisperDownloadedState) + const downloadedModelsFugumt = useRecoilValue(modelFugumtDownloadedState) const [transcriptionAccuracy, setTranscriptionAccuracy] = useRecoilState(transcriptionAccuracyState) const isRecording = useRecoilValue(recordState) const isTracing = useRecoilValue(tracingState); @@ -43,9 +45,8 @@ const TranscriptionAccuracy = (): JSX.Element => { case "large": return "文字起こし:高"; case "large-distil.en": - return "文字起こし:英"; case "large-distil.ja": - return "文字起こし:日"; + return "文字起こし:速度優先"; case "online-transcript": return "文字起こし:WhisperAPI"; case "online-transcript-to-en": @@ -60,6 +61,8 @@ const TranscriptionAccuracy = (): JSX.Element => { return "翻訳(英):中"; case "large-translate-to-en": return "翻訳(英):高"; + case "fugumt-en-ja": + return "翻訳(日):速度優先"; default: throw new Error("unknown modelType: " + model); } @@ -67,7 +70,16 @@ const TranscriptionAccuracy = (): JSX.Element => { return (
- {((isRecording || isTracing) || (downloadedModels.length === 0 && settingKeyOpenai === "" && !(settingKeyAmivoice !== "" && (speakerLanguage?.startsWith("ja") || speakerLanguage?.startsWith("small-ja"))))) ?
+
+
+
+

翻訳パック(日本語:速度優先)

+

※ 翻訳パックを有効にするには、言語パック(汎用:高)も必要です。

+
+ +
+ +
diff --git a/src/store/atoms/modelFugumtDownloadedState.ts b/src/store/atoms/modelFugumtDownloadedState.ts new file mode 100644 index 0000000..cf1d699 --- /dev/null +++ b/src/store/atoms/modelFugumtDownloadedState.ts @@ -0,0 +1,22 @@ +import { atom, AtomEffect } from 'recoil' +import DB from '../../lib/sqlite'; + +const sqliteEffect: AtomEffect = ({setSelf, trigger}) => { + const loadPersisted = async () => { + const db = (await DB.getInstance()) + const savedValue = await db.loadDownloadedModels("fugumt"); + setSelf(savedValue.map(obj=>obj.model_name)); + }; + + if (trigger === 'get') { + loadPersisted(); + } +}; + +export const modelFugumtDownloadedState = atom({ + key: 'modelFugumtDownloadedState', + default: [], + effects: [ + sqliteEffect, + ] +}) \ No newline at end of file diff --git a/src/store/atoms/modelFugumtDownloadingState.ts b/src/store/atoms/modelFugumtDownloadingState.ts new file mode 100644 index 0000000..8373f55 --- /dev/null +++ b/src/store/atoms/modelFugumtDownloadingState.ts @@ -0,0 +1,6 @@ +import { atom } from 'recoil' + +export const modelFugumtDownloadingState = atom({ + key: 'modelFugumtDownloadingState', + default: [] +}) \ No newline at end of file