diff --git a/.github/scripts/test-rust.sh b/.github/scripts/test-rust.sh index 22712e27b9..2d8360f8bd 100755 --- a/.github/scripts/test-rust.sh +++ b/.github/scripts/test-rust.sh @@ -6,4 +6,5 @@ cd rust-api-examples ./run-version.sh -./run-streaming-zipformer.sh +./run-streaming-zipformer-en.sh +./run-streaming-zipformer-zh-en.sh diff --git a/rust-api-examples/.gitignore b/rust-api-examples/.gitignore index eb5a316cbd..9d63ddfe38 100644 --- a/rust-api-examples/.gitignore +++ b/rust-api-examples/.gitignore @@ -1 +1,2 @@ target +!run-*.sh diff --git a/rust-api-examples/Cargo.lock b/rust-api-examples/Cargo.lock index cf16558f68..34bf8c3fd2 100644 --- a/rust-api-examples/Cargo.lock +++ b/rust-api-examples/Cargo.lock @@ -2,18 +2,537 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "alsa" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43" +dependencies = [ + "alsa-sys", + "bitflags 2.11.0", + "cfg-if", + "libc", +] + +[[package]] +name = "alsa-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "clap" +version = "4.5.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "coreaudio-rs" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aae284fbaf7d27aa0e292f7677dfbe26503b0d555026f702940805a630eac17" +dependencies = [ + "bitflags 1.3.2", + "libc", + "objc2-audio-toolbox", + "objc2-core-audio", + "objc2-core-audio-types", + "objc2-core-foundation", +] + +[[package]] +name = "cpal" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbd307f43cc2a697e2d1f8bc7a1d824b5269e052209e28883e5bc04d095aaa3f" +dependencies = [ + "alsa", + "coreaudio-rs", + "dasp_sample", + "jni", + "js-sys", + "libc", + "mach2", + "ndk", + "ndk-context", + "num-derive", + "num-traits", + "objc2-audio-toolbox", + "objc2-core-audio", + "objc2-core-audio-types", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows", +] + +[[package]] +name = "dasp_sample" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" + +[[package]] +name = "dispatch2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +dependencies = [ + "bitflags 2.11.0", + "objc2", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "indexmap" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + [[package]] name = "itoa" version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "js-sys" +version = "0.3.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4eacb0641a310445a4c513f2a5e23e19952e269c6a38887254d5f837a305506" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.182" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "mach2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" +dependencies = [ + "libc", +] + [[package]] name = "memchr" version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.11.0", + "jni-sys", + "log", + "ndk-sys", + "num_enum", + "thiserror", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_enum" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "objc2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-audio-toolbox" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6948501a91121d6399b79abaa33a8aa4ea7857fe019f341b8c23ad6e81b79b08" +dependencies = [ + "bitflags 2.11.0", + "libc", + "objc2", + "objc2-core-audio", + "objc2-core-audio-types", + "objc2-core-foundation", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-audio" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1eebcea8b0dbff5f7c8504f3107c68fc061a3eb44932051c8cf8a68d969c3b2" +dependencies = [ + "dispatch2", + "objc2", + "objc2-core-audio-types", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-core-audio-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a89f2ec274a0cf4a32642b2991e8b351a404d290da87bb6a9a9d8632490bd1c" +dependencies = [ + "bitflags 2.11.0", + "objc2", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.11.0", + "dispatch2", + "objc2", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "objc2", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "proc-macro-crate" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +dependencies = [ + "toml_edit", +] + [[package]] name = "proc-macro2" version = "1.0.106" @@ -34,11 +553,29 @@ dependencies = [ [[package]] name = "rust-api-examples" -version = "0.1.1" +version = "0.1.2" dependencies = [ + "anyhow", + "clap", + "cpal", "sherpa-onnx", ] +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "serde" version = "1.0.228" @@ -84,9 +621,9 @@ dependencies = [ [[package]] name = "sherpa-onnx" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9678e5b5315d1bad0b78c7be2e27820ec9fce51d814b844aa8b5cd64fc36e417" +checksum = "e4d39df68ea4190e2459c499bcff26b23fddc4f4573eb67adab4d286c078b70a" dependencies = [ "serde", "serde_json", @@ -95,9 +632,21 @@ dependencies = [ [[package]] name = "sherpa-onnx-sys" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50208e12ba107c6d3063d28e69d1855fd81d032cf197fc04c4e343f7f7f1ac7f" +checksum = "be7ecbb1d8d122338507d0abdac0e45ea8468b7e37cb5f12aca71c74a7b312de" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" @@ -110,12 +659,339 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml_datetime" +version = "0.7.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.23.10+spec-1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.9+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" +dependencies = [ + "winnow", +] + [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05d7d0fce354c88b7982aec4400b3e7fcf723c32737cef571bd165f7613557ee" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.62" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee85afca410ac4abba5b584b12e77ea225db6ee5471d0aebaae0861166f9378a" +dependencies = [ + "cfg-if", + "futures-util", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55839b71ba921e4f75b674cb16f843f4b1f3b26ddfcb3454de1cf65cc021ec0f" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf2e969c2d60ff52e7e98b7392ff1588bffdd1ccd4769eba27222fd3d621571" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0861f0dcdf46ea819407495634953cdcc8a8c7215ab799a7a7ce366be71c7b30" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10053fbf9a374174094915bbce141e87a6bf32ecd9a002980db4b638405e8962" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "windows" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" +dependencies = [ + "windows-core", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +dependencies = [ + "memchr", +] + [[package]] name = "zmij" version = "1.0.21" diff --git a/rust-api-examples/Cargo.toml b/rust-api-examples/Cargo.toml index 587b76168e..05646a84b0 100644 --- a/rust-api-examples/Cargo.toml +++ b/rust-api-examples/Cargo.toml @@ -1,9 +1,23 @@ [package] name = "rust-api-examples" -version = "0.1.1" +version = "0.1.2" edition = "2021" - [dependencies] -sherpa-onnx = "0.1.1" +anyhow = "1.0" +clap = { version = "4.5", features = ["derive"] } +sherpa-onnx = "0.1.2" # sherpa-onnx = { path = "../sherpa-onnx/rust/sherpa-onnx" } + +cpal = { version = "0.16", optional = true } # cross-platform audio I/O + +[features] +# Default features are empty to avoid building cpal by default +default = [] + +# Feature for using microphone +mic = ["cpal"] + +[[example]] +name = "streaming_zipformer_microphone" +required-features = ["mic"] diff --git a/rust-api-examples/README.md b/rust-api-examples/README.md index be6c5fd919..9929781c3b 100644 --- a/rust-api-examples/README.md +++ b/rust-api-examples/README.md @@ -43,7 +43,7 @@ otool -l target/debug/examples/version | grep -A2 LC_RPATH ``` to check the RPATH. -### Example 2: ASR with streaming zipformer +### Example 2: ASR with streaming zipformer (with a file) ```bash wget https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-streaming-zipformer-en-2023-06-21.tar.bz2 @@ -51,7 +51,30 @@ wget https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-o tar xvf sherpa-onnx-streaming-zipformer-en-2023-06-21.tar.bz2 rm sherpa-onnx-streaming-zipformer-en-2023-06-21.tar.bz2 -cargo run --example streaming_zipformer +cargo run --example streaming_zipformer -- \ + --wav sherpa-onnx-streaming-zipformer-en-2023-06-21/test_wavs/1.wav \ + --encoder sherpa-onnx-streaming-zipformer-en-2023-06-21/encoder-epoch-99-avg-1.int8.onnx \ + --decoder sherpa-onnx-streaming-zipformer-en-2023-06-21/decoder-epoch-99-avg-1.onnx \ + --joiner sherpa-onnx-streaming-zipformer-en-2023-06-21/joiner-epoch-99-avg-1.int8.onnx \ + --tokens sherpa-onnx-streaming-zipformer-en-2023-06-21/tokens.txt \ + --provider cpu \ + --debug +``` + +### Example 3: ASR with streaming zipformer (with a microphone, real-time ASR) + +```bash +wget https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20.tar.bz2 +tar xvf sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20.tar.bz2 +rm sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20.tar.bz2 + +cargo run --example streaming_zipformer_microphone --features mic -- \ + --encoder sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/encoder-epoch-99-avg-1.int8.onnx \ + --decoder sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/decoder-epoch-99-avg-1.onnx \ + --joiner sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/joiner-epoch-99-avg-1.int8.onnx \ + --tokens sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/tokens.txt \ + --provider cpu \ + --debug ``` # Alternative rust bindings for sherpa-onnx diff --git a/rust-api-examples/examples/streaming_zipformer.rs b/rust-api-examples/examples/streaming_zipformer.rs index 54609606b2..7bd7fe70d0 100644 --- a/rust-api-examples/examples/streaming_zipformer.rs +++ b/rust-api-examples/examples/streaming_zipformer.rs @@ -6,41 +6,65 @@ // See ../README.md for how to run it // // Note that even if we use a wave file as an example, this model supports -// real-time streaming speech recognition. You can read audio samples -// from a microphone. +// real-time streaming speech recognition. +// See ./streaming_zipformer_microphone.rs for how to do real-time +// streaming speech recognition from a microphone. +use clap::Parser; use sherpa_onnx::{OnlineRecognizer, OnlineRecognizerConfig, Wave}; +/// Simple streaming Zipformer example +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +struct Args { + /// Path to WAV file + #[arg(long)] + wav: String, + + /// Path to encoder ONNX model + #[arg(long)] + encoder: String, + + /// Path to decoder ONNX model + #[arg(long)] + decoder: String, + + /// Path to joiner ONNX model + #[arg(long)] + joiner: String, + + /// Path to tokens file + #[arg(long)] + tokens: String, + + /// Provider (default: cpu) + #[arg(long, default_value = "cpu")] + provider: String, + + /// Enable debug logs + #[arg(long, default_value_t = false)] + debug: bool, +} + fn main() { - let wav_path = "sherpa-onnx-streaming-zipformer-en-2023-06-21/test_wavs/1.wav"; - let encoder_path = - "sherpa-onnx-streaming-zipformer-en-2023-06-21/encoder-epoch-99-avg-1.int8.onnx"; - let decoder_path = "sherpa-onnx-streaming-zipformer-en-2023-06-21/decoder-epoch-99-avg-1.onnx"; - let joiner_path = - "sherpa-onnx-streaming-zipformer-en-2023-06-21/joiner-epoch-99-avg-1.int8.onnx"; - let tokens_path = "sherpa-onnx-streaming-zipformer-en-2023-06-21/tokens.txt"; - let provider = "cpu"; + let args = Args::parse(); - let wave = Wave::read(wav_path).expect("Failed to read WAV file"); + let wave = Wave::read(&args.wav).expect("Failed to read WAV file"); let mut recognizer_config = OnlineRecognizerConfig::default(); - recognizer_config.model_config.transducer.encoder = Some(encoder_path.to_string()); - recognizer_config.model_config.transducer.decoder = Some(decoder_path.to_string()); - recognizer_config.model_config.transducer.joiner = Some(joiner_path.to_string()); - recognizer_config.model_config.tokens = Some(tokens_path.to_string()); - recognizer_config.model_config.provider = Some(provider.to_string()); + recognizer_config.model_config.transducer.encoder = Some(args.encoder.clone()); + recognizer_config.model_config.transducer.decoder = Some(args.decoder.clone()); + recognizer_config.model_config.transducer.joiner = Some(args.joiner.clone()); + recognizer_config.model_config.tokens = Some(args.tokens.clone()); + recognizer_config.model_config.provider = Some(args.provider.clone()); recognizer_config.enable_endpoint = true; - - // set to true to see verbose logs - recognizer_config.model_config.debug = true; - + recognizer_config.model_config.debug = args.debug; recognizer_config.decoding_method = Some("greedy_search".to_string()); let recognizer = OnlineRecognizer::create(&recognizer_config).expect("Failed to create OnlineRecognizer"); let stream = recognizer.create_stream(); - let mut segment_id = 0; // use any positive value as you like @@ -53,6 +77,7 @@ fn main() { wave.num_samples() as f32 / wave.sample_rate() as f32 ); + // Process in chunks for chunk in wave.samples().chunks(CHUNK_SIZE) { stream.accept_waveform(wave.sample_rate(), chunk); @@ -75,7 +100,6 @@ fn main() { // Tail padding (~0.3s) let tail_padding_len = (wave.sample_rate() as f32 * 0.3).round() as usize; let tail_padding = vec![0.0f32; tail_padding_len]; - stream.accept_waveform(wave.sample_rate(), &tail_padding); stream.input_finished(); diff --git a/rust-api-examples/examples/streaming_zipformer_microphone.rs b/rust-api-examples/examples/streaming_zipformer_microphone.rs new file mode 100644 index 0000000000..0a03437bcd --- /dev/null +++ b/rust-api-examples/examples/streaming_zipformer_microphone.rs @@ -0,0 +1,235 @@ +// Copyright (c) 2026 Xiaomi Corporation +// +// This file demonstrates how to use streaming Zipformer with sherpa-onnx's +// Rust API for real-time streaming speech recognition with a microphone. +// +// See ../README.md for how to run it +// +// See ./streaming_zipformer.rs for how to recognize a wave file. + +use anyhow::Result; +use clap::Parser; +use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; +use cpal::SampleFormat; +use sherpa_onnx::{DisplayManager, OnlineRecognizer, OnlineRecognizerConfig}; +use std::sync::mpsc; + +/// Command-line arguments +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +struct Args { + #[arg(long)] + encoder: String, + #[arg(long)] + decoder: String, + #[arg(long)] + joiner: String, + #[arg(long)] + tokens: String, + #[arg(long, default_value = "cpu")] + provider: String, + #[arg(long, default_value_t = false)] + debug: bool, + #[arg(long, default_value_t = 3200)] + chunk_size: usize, +} + +/// List input devices and return the default one +fn list_input_devices(host: &cpal::Host) -> Result { + let default_input = host.default_input_device(); + let default_name = default_input.as_ref().map(|d| d.name().unwrap_or_default()); + + println!("Available input devices:"); + for device in host.input_devices()? { + let name = device.name().unwrap_or("".to_string()); + let mark = if Some(&name) == default_name.as_ref() { + "*" + } else { + " " + }; + println!("{} {}", mark, name); + } + + let device = default_input.ok_or_else(|| anyhow::anyhow!("No default input device"))?; + + println!("\nUsing default device: {}", device.name()?); + Ok(device) +} + +/// Create and configure the OnlineRecognizer +fn setup_recognizer(args: &Args) -> OnlineRecognizer { + let mut config = OnlineRecognizerConfig::default(); + config.model_config.transducer.encoder = Some(args.encoder.clone()); + config.model_config.transducer.decoder = Some(args.decoder.clone()); + config.model_config.transducer.joiner = Some(args.joiner.clone()); + config.model_config.tokens = Some(args.tokens.clone()); + config.model_config.provider = Some(args.provider.clone()); + config.model_config.debug = args.debug; + config.enable_endpoint = true; + config.decoding_method = Some("greedy_search".to_string()); + + OnlineRecognizer::create(&config).expect("Failed to create OnlineRecognizer") +} + +/// Build the audio input stream (producer) +fn build_input_stream(device: &cpal::Device, tx: mpsc::Sender>) -> Result { + let supported = device.default_input_config()?; + let config = supported.config(); + let sample_format = supported.sample_format(); + let channels = config.channels as usize; + + let err_fn = |err| eprintln!("Audio stream error: {:?}", err); + + println!( + "Input format: {:?}, channels: {}, sample_rate: {}", + sample_format, channels, config.sample_rate.0 + ); + + let stream = match sample_format { + SampleFormat::F32 => device.build_input_stream( + &config, + move |data: &[f32], _| { + if data.is_empty() { + return; + } + + let mono: Vec = data + .chunks(channels) + .map(|frame| { + let sum: f32 = frame.iter().copied().sum(); + sum / channels as f32 + }) + .collect(); + let _ = tx.send(mono); + }, + err_fn, + None, + )?, + + SampleFormat::I16 => device.build_input_stream( + &config, + move |data: &[i16], _| { + if data.is_empty() { + return; + } + + let mono: Vec = data + .chunks(channels) + .map(|frame| { + let sum: f32 = frame.iter().map(|&s| s as f32 / i16::MAX as f32).sum(); + sum / channels as f32 + }) + .collect(); + + let _ = tx.send(mono); + }, + err_fn, + None, + )?, + + SampleFormat::U16 => device.build_input_stream( + &config, + move |data: &[u16], _| { + if data.is_empty() { + return; + } + + let mono: Vec = data + .chunks(channels) + .map(|frame| { + let sum: f32 = frame + .iter() + .map(|&s| { + let centered = s as f32 - 32768.0; + centered / 32768.0 + }) + .sum(); + sum / channels as f32 + }) + .collect(); + + let _ = tx.send(mono); + }, + err_fn, + None, + )?, + + other => anyhow::bail!("Unsupported sample format: {:?}", other), + }; + + Ok(stream) +} + +/// Main recognition loop (consumer) +fn run_recognition_loop( + rx: mpsc::Receiver>, + recognizer: &OnlineRecognizer, + stream: &mut sherpa_onnx::OnlineStream, + chunk_size: usize, + sample_rate: i32, +) { + let mut display = DisplayManager::new(); + let mut buffer = Vec::::new(); + + loop { + match rx.recv() { + Ok(samples) => { + buffer.extend_from_slice(&samples); + } + Err(_) => { + println!("\nAudio stream closed. Exiting."); + break; + } + } + + while buffer.len() >= chunk_size { + let chunk: Vec = buffer.drain(..chunk_size).collect(); + stream.accept_waveform(sample_rate, &chunk); + + while recognizer.is_ready(&stream) { + recognizer.decode(&stream); + + if let Some(result) = recognizer.get_result(&stream) { + let text = result.text; + if !text.is_empty() { + display.update_text(&text); + } + } + + if recognizer.is_endpoint(&stream) { + if let Some(result) = recognizer.get_result(&stream) { + if !result.text.is_empty() { + display.finalize_sentence(); + } + } + recognizer.reset(&stream); + } + } + } + + display.render(); + } +} + +fn main() -> Result<()> { + let args = Args::parse(); + let host = cpal::default_host(); + + let device = list_input_devices(&host)?; + + let supported = device.default_input_config()?; + let sample_rate = supported.sample_rate().0 as i32; + + let recognizer = setup_recognizer(&args); + let mut stream = recognizer.create_stream(); + + let (tx, rx) = mpsc::channel::>(); + let audio_stream = build_input_stream(&device, tx)?; + audio_stream.play()?; + + println!("Streaming microphone ASR... Press Ctrl+C to stop."); + + run_recognition_loop(rx, &recognizer, &mut stream, args.chunk_size, sample_rate); + + Ok(()) +} diff --git a/rust-api-examples/run-streaming-zipformer-en.sh b/rust-api-examples/run-streaming-zipformer-en.sh new file mode 100755 index 0000000000..d16c491c8a --- /dev/null +++ b/rust-api-examples/run-streaming-zipformer-en.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +set -ex + +# see +# https://k2-fsa.github.io/sherpa/onnx/pretrained_models/online-transducer/zipformer-transducer-models.html#csukuangfj-sherpa-onnx-streaming-zipformer-en-2023-06-21-english +if [ ! -f ./sherpa-onnx-streaming-zipformer-en-2023-06-21/encoder-epoch-99-avg-1.int8.onnx ]; then + curl -SsL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-streaming-zipformer-en-2023-06-21.tar.bz2 + + tar xvf sherpa-onnx-streaming-zipformer-en-2023-06-21.tar.bz2 + rm sherpa-onnx-streaming-zipformer-en-2023-06-21.tar.bz2 + ls -lh sherpa-onnx-streaming-zipformer-en-2023-06-21 +fi + +cargo run --example streaming_zipformer -- \ + --wav sherpa-onnx-streaming-zipformer-en-2023-06-21/test_wavs/1.wav \ + --encoder sherpa-onnx-streaming-zipformer-en-2023-06-21/encoder-epoch-99-avg-1.int8.onnx \ + --decoder sherpa-onnx-streaming-zipformer-en-2023-06-21/decoder-epoch-99-avg-1.onnx \ + --joiner sherpa-onnx-streaming-zipformer-en-2023-06-21/joiner-epoch-99-avg-1.int8.onnx \ + --tokens sherpa-onnx-streaming-zipformer-en-2023-06-21/tokens.txt \ + --provider cpu \ + --debug diff --git a/rust-api-examples/run-streaming-zipformer-microphone-zh-en.sh b/rust-api-examples/run-streaming-zipformer-microphone-zh-en.sh new file mode 100755 index 0000000000..cde6491919 --- /dev/null +++ b/rust-api-examples/run-streaming-zipformer-microphone-zh-en.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -ex + +# see +# https://k2-fsa.github.io/sherpa/onnx/pretrained_models/online-transducer/zipformer-transducer-models.html#csukuangfj-sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20-bilingual-chinese-english +if [ ! -f ./sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/encoder-epoch-99-avg-1.int8.onnx ]; then + curl -SsL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20.tar.bz2 + tar xvf sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20.tar.bz2 + rm sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20.tar.bz2 + ls -lh sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20 +fi + +cargo run --example streaming_zipformer_microphone --features mic -- \ + --encoder sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/encoder-epoch-99-avg-1.int8.onnx \ + --decoder sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/decoder-epoch-99-avg-1.onnx \ + --joiner sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/joiner-epoch-99-avg-1.int8.onnx \ + --tokens sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/tokens.txt \ + --provider cpu \ + --debug diff --git a/rust-api-examples/run-streaming-zipformer-zh-en.sh b/rust-api-examples/run-streaming-zipformer-zh-en.sh new file mode 100755 index 0000000000..00d0fa7b9f --- /dev/null +++ b/rust-api-examples/run-streaming-zipformer-zh-en.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -ex + +# see +# https://k2-fsa.github.io/sherpa/onnx/pretrained_models/online-transducer/zipformer-transducer-models.html#csukuangfj-sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20-bilingual-chinese-english +if [ ! -f ./sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/encoder-epoch-99-avg-1.int8.onnx ]; then + curl -SsL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20.tar.bz2 + tar xvf sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20.tar.bz2 + rm sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20.tar.bz2 + ls -lh sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20 +fi + +cargo run --example streaming_zipformer -- \ + --wav sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/test_wavs/2.wav \ + --encoder sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/encoder-epoch-99-avg-1.int8.onnx \ + --decoder sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/decoder-epoch-99-avg-1.onnx \ + --joiner sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/joiner-epoch-99-avg-1.int8.onnx \ + --tokens sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/tokens.txt \ + --provider cpu \ + --debug diff --git a/rust-api-examples/run-streaming-zipformer.sh b/rust-api-examples/run-streaming-zipformer.sh deleted file mode 100755 index 8866340c38..0000000000 --- a/rust-api-examples/run-streaming-zipformer.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash -set -ex - -if [ ! -f ./sherpa-onnx-streaming-zipformer-en-2023-06-21/encoder-epoch-99-avg-1.int8.onnx ]; then - curl -SsL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-streaming-zipformer-en-2023-06-21.tar.bz2 - - tar xvf sherpa-onnx-streaming-zipformer-en-2023-06-21.tar.bz2 - rm sherpa-onnx-streaming-zipformer-en-2023-06-21.tar.bz2 - ls -lh sherpa-onnx-streaming-zipformer-en-2023-06-21 -fi - -cargo run --example streaming_zipformer diff --git a/sherpa-onnx/rust/sherpa-onnx-sys/Cargo.toml b/sherpa-onnx/rust/sherpa-onnx-sys/Cargo.toml index dd761cb870..8fd045b07a 100644 --- a/sherpa-onnx/rust/sherpa-onnx-sys/Cargo.toml +++ b/sherpa-onnx/rust/sherpa-onnx-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sherpa-onnx-sys" -version = "0.1.1" +version = "0.1.2" edition = "2021" description = "Raw FFI bindings to the sherpa-onnx C API" license = "Apache-2.0" diff --git a/sherpa-onnx/rust/sherpa-onnx/Cargo.toml b/sherpa-onnx/rust/sherpa-onnx/Cargo.toml index a7ed81bbe1..7ade275fd0 100644 --- a/sherpa-onnx/rust/sherpa-onnx/Cargo.toml +++ b/sherpa-onnx/rust/sherpa-onnx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sherpa-onnx" -version = "0.1.1" +version = "0.1.2" edition = "2021" description = "Safe Rust wrapper for sherpa-onnx speech recognition toolkit" license = "Apache-2.0" @@ -20,6 +20,6 @@ include = [ ] [dependencies] -sherpa-onnx-sys = { path = "../sherpa-onnx-sys", version = "0.1.1" } +sherpa-onnx-sys = { path = "../sherpa-onnx-sys", version = "0.1.2" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/sherpa-onnx/rust/sherpa-onnx/src/display.rs b/sherpa-onnx/rust/sherpa-onnx/src/display.rs new file mode 100644 index 0000000000..3719ce6795 --- /dev/null +++ b/sherpa-onnx/rust/sherpa-onnx/src/display.rs @@ -0,0 +1,88 @@ +// Display manager for streaming ASR, inspired by sherpa-display.h +// Handles finalized sentences and current partial text. + +use std::time::{Duration, Instant}; + +/// DisplayManager stores finalized sentences and current partial text +#[derive(Debug)] +pub struct DisplayManager { + sentences: Vec, + current_text: String, + last_render: Instant, +} + +impl DisplayManager { + /// Create a new DisplayManager + pub fn new() -> Self { + Self { + sentences: Vec::new(), + current_text: String::new(), + last_render: Instant::now(), + } + } + + /// Update the current partial text + pub fn update_text(&mut self, text: &str) { + self.current_text = text.to_string(); + } + + /// Finalize the current sentence and move it to `sentences` + pub fn finalize_sentence(&mut self) { + let trimmed = self + .current_text + .trim(); + if !trimmed.is_empty() { + self.sentences + .push(trimmed.to_string()); + } + self.current_text + .clear(); + } + + /// Render the display to stdout + /// Clears the screen and prints finalized + current text + pub fn render(&mut self) { + // Throttle rendering to reduce flicker (200ms) + if self + .last_render + .elapsed() + < Duration::from_millis(200) + { + return; + } + self.last_render = Instant::now(); + + // Clear screen (ANSI escape) + print!("\x1B[2J\x1B[1;1H"); + println!("=== Speech Recognition with Next-gen Kaldi ==="); + println!("-----------------------------------------------"); + + for (i, s) in self + .sentences + .iter() + .enumerate() + { + println!("{}: {}", i + 1, s); + } + + if !self + .current_text + .is_empty() + { + println!("-----------------------------------------------"); + println!("Recognizing: {}", self.current_text); + } + } + + /// Returns true if there are finalized sentences + pub fn has_sentences(&self) -> bool { + !self + .sentences + .is_empty() + } + + /// Returns current partial text + pub fn current_text(&self) -> &str { + &self.current_text + } +} diff --git a/sherpa-onnx/rust/sherpa-onnx/src/lib.rs b/sherpa-onnx/rust/sherpa-onnx/src/lib.rs index 957f08d7de..edce8a74f4 100644 --- a/sherpa-onnx/rust/sherpa-onnx/src/lib.rs +++ b/sherpa-onnx/rust/sherpa-onnx/src/lib.rs @@ -1,7 +1,9 @@ +mod display; mod online_asr; mod utils; mod wave; +pub use display::*; pub use online_asr::*; pub use utils::*; pub use wave::*;