commit 3c79d274508db181824a4dbe7a797db1ac0eba19 Author: Uttarayan Mondal Date: Sat May 29 21:56:42 2021 +0530 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..ea8c4bf7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 00000000..7f1b857d --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,283 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "ctor" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e98e2ad1a782e33928b96fc3948e7c355e5af34ba4de7670fe8bac2a3b2006d" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "ghost" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5bcf1bbeab73aa4cf2fde60a846858dc036163c7c33bec309f8d17de785479" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "google_speech" +version = "0.1.0" +dependencies = [ + "pyo3", +] + +[[package]] +name = "indoc" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47741a8bc60fb26eb8d6e0238bbb26d8575ff623fdc97b1a2c00c050b9684ed8" +dependencies = [ + "indoc-impl", + "proc-macro-hack", +] + +[[package]] +name = "indoc-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce046d161f000fffde5f432a0d034d0341dc152643b2598ed5bfce44c4f3a8f0" +dependencies = [ + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", + "unindent", +] + +[[package]] +name = "instant" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "inventory" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f0f7efb804ec95e33db9ad49e4252f049e37e8b0a4652e3cd61f7999f2eff7f" +dependencies = [ + "ctor", + "ghost", + "inventory-impl", +] + +[[package]] +name = "inventory-impl" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75c094e94816723ab936484666968f5b58060492e880f3c8d00489a1e244fa51" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "libc" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36" + +[[package]] +name = "lock_api" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "parking_lot" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "paste" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" +dependencies = [ + "paste-impl", + "proc-macro-hack", +] + +[[package]] +name = "paste-impl" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" +dependencies = [ + "proc-macro-hack", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" + +[[package]] +name = "proc-macro2" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "pyo3" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4837b8e8e18a102c23f79d1e9a110b597ea3b684c95e874eb1ad88f8683109c3" +dependencies = [ + "cfg-if", + "ctor", + "indoc", + "inventory", + "libc", + "parking_lot", + "paste", + "pyo3-macros", + "unindent", +] + +[[package]] +name = "pyo3-macros" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47f2c300ceec3e58064fd5f8f5b61230f2ffd64bde4970c81fdd0563a2db1bb" +dependencies = [ + "pyo3-macros-backend", + "quote", + "syn", +] + +[[package]] +name = "pyo3-macros-backend" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87b097e5d84fcbe3e167f400fbedd657820a375b034c78bd852050749a575d66" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "quote" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc" +dependencies = [ + "bitflags", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "smallvec" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" + +[[package]] +name = "syn" +version = "1.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "unindent" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f14ee04d9415b52b3aeab06258a3f07093182b88ba0f9b8d203f211a7a7d41c7" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 00000000..1752cf6c --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "google_speech" +version = "0.1.0" +authors = ["Uttarayan Mondal "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +pyo3 = "0.13.2" diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 00000000..bbdb9406 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,2 @@ +pub mod tts; +pub use tts::{Lang, Speech}; diff --git a/src/tts.rs b/src/tts.rs new file mode 100644 index 00000000..a677503b --- /dev/null +++ b/src/tts.rs @@ -0,0 +1,220 @@ +use pyo3::prelude::*; +use pyo3::types::IntoPyDict; +#[derive(Debug)] +pub struct Speech { + pyobject_speech: PyObject, +} +impl Speech { + /// Create a new speech object with language + pub fn new>(text: S, lang: Lang) -> PyResult { + Python::with_gil(|py| { + let google_speech = PyModule::import(py, "google_speech").unwrap(); + let pyobject_speech: PyObject = google_speech + .call1("Speech", (text.as_ref(), lang.to_string())) + .unwrap() + .extract() + .unwrap(); + Ok(Self { pyobject_speech }) + }) + } + + /// Play the speech object + pub fn play(&self) -> PyResult<()> { + Python::with_gil(|py| { + self.pyobject_speech.call_method0(py, "play")?; + Ok(()) + }) + } + + /// # Safety + /// The save function is a wrapper around google_speech.Speech.save + /// which might be unsafe + pub unsafe fn save>(&self, path: S) -> PyResult<()> { + Python::with_gil(|py| { + self.pyobject_speech + .call_method1(py, "save", (path.as_ref(),))?; + Ok(()) + }) + } + + // /// Change the language + // pub fn lang(&mut self, lang: Lang) -> PyResult<()> { + // Python::with_gil(|py| { + // // self.pyobject_speech.getattr + // // let globals = PyDict:: + // Python::run( + // py, + // // &format!("speech.lang = \"{}\"", lang.to_string()), + // &format!("print(\"{}\")", lang.to_string()), + // Some(vec![("speech", lang.to_string().as_str())].into_py_dict(py)), + // None, + // )?; + // println!("{:?}", self.pyobject_speech); + // Ok(()) + // }) + // } +} + +#[allow(non_camel_case_types)] +#[derive(Debug)] +#[non_exhaustive] +pub enum Lang { + af, + ar, + bn, + bs, + ca, + cs, + cy, + da, + de, + el, + en, + en_au, + en_ca, + en_gb, + en_gh, + en_ie, + en_in, + en_ng, + en_nz, + en_ph, + en_tz, + en_uk, + en_us, + en_za, + eo, + es, + es_es, + es_us, + et, + fi, + fr, + fr_ca, + fr_fr, + hi, + hr, + hu, + hy, + id, + is, + it, + ja, + jw, + km, + ko, + la, + lv, + mk, + ml, + mr, + my, + ne, + nl, + no, + pl, + pt, + pt_br, + pt_pt, + ro, + ru, + si, + sk, + sq, + sr, + su, + sv, + sw, + ta, + te, + th, + tl, + tr, + uk, + vi, + zh_cn, + zh_tw, +} + +impl ToString for Lang { + fn to_string(&self) -> String { + let ret = match self { + Lang::af => "af", + Lang::ar => "ar", + Lang::bn => "bn", + Lang::bs => "bs", + Lang::ca => "ca", + Lang::cs => "cs", + Lang::cy => "cy", + Lang::da => "da", + Lang::de => "de", + Lang::el => "el", + Lang::en => "en", + Lang::en_au => "en-au", + Lang::en_ca => "en-ca", + Lang::en_gb => "en-gb", + Lang::en_gh => "en-gh", + Lang::en_ie => "en-ie", + Lang::en_in => "en-in", + Lang::en_ng => "en-ng", + Lang::en_nz => "en-nz", + Lang::en_ph => "en-ph", + Lang::en_tz => "en-tz", + Lang::en_uk => "en-uk", + Lang::en_us => "en-us", + Lang::en_za => "en-za", + Lang::eo => "eo", + Lang::es => "es", + Lang::es_es => "es-es", + Lang::es_us => "es-us", + Lang::et => "et", + Lang::fi => "fi", + Lang::fr => "fr", + Lang::fr_ca => "fr-ca", + Lang::fr_fr => "fr-fr", + Lang::hi => "hi", + Lang::hr => "hr", + Lang::hu => "hu", + Lang::hy => "hy", + Lang::id => "id", + Lang::is => "is", + Lang::it => "it", + Lang::ja => "ja", + Lang::jw => "jw", + Lang::km => "km", + Lang::ko => "ko", + Lang::la => "la", + Lang::lv => "lv", + Lang::mk => "mk", + Lang::ml => "ml", + Lang::mr => "mr", + Lang::my => "my", + Lang::ne => "ne", + Lang::nl => "nl", + Lang::no => "no", + Lang::pl => "pl", + Lang::pt => "pt", + Lang::pt_br => "pt-br", + Lang::pt_pt => "pt-pt", + Lang::ro => "ro", + Lang::ru => "ru", + Lang::si => "si", + Lang::sk => "sk", + Lang::sq => "sq", + Lang::sr => "sr", + Lang::su => "su", + Lang::sv => "sv", + Lang::sw => "sw", + Lang::ta => "ta", + Lang::te => "te", + Lang::th => "th", + Lang::tl => "tl", + Lang::tr => "tr", + Lang::uk => "uk", + Lang::vi => "vi", + Lang::zh_cn => "zh-cn", + Lang::zh_tw => "zh-tw", + }; + ret.to_string() + } +} diff --git a/tests/tests.rs b/tests/tests.rs new file mode 100644 index 00000000..bc4c2528 --- /dev/null +++ b/tests/tests.rs @@ -0,0 +1,20 @@ +use google_speech::{Lang, Speech}; +#[test] +fn test_hello_play() { + let hello = Speech::new("Hello", Lang::en_us).unwrap(); + hello.play().unwrap(); +} + +#[test] +fn test_hello_save() { + let hello = Speech::new("Hello", Lang::en_us).unwrap(); + unsafe { hello.save("target/hello.mp3").unwrap() }; +} + +// #[test] +// fn test_hello_lang() { +// let mut hello = Speech::new("Hello", Lang::af).unwrap(); +// hello.play().unwrap(); +// hello.lang(Lang::en_us).unwrap(); +// hello.play().unwrap(); +// }