Matrix commited on
Commit
2bb7b57
1 Parent(s): d33bba5

chore: cargo fmt

Browse files
Files changed (7) hide show
  1. Cargo.lock +140 -125
  2. Cargo.toml +6 -6
  3. src/config.rs +15 -10
  4. src/group.rs +21 -17
  5. src/lesson.rs +56 -65
  6. src/main.rs +50 -31
  7. src/whisper.rs +77 -47
Cargo.lock CHANGED
@@ -93,7 +93,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
93
  dependencies = [
94
  "proc-macro2",
95
  "quote",
96
- "syn 2.0.38",
97
  ]
98
 
99
  [[package]]
@@ -104,7 +104,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9"
104
  dependencies = [
105
  "proc-macro2",
106
  "quote",
107
- "syn 2.0.38",
108
  ]
109
 
110
  [[package]]
@@ -135,7 +135,7 @@ dependencies = [
135
  "hex",
136
  "http",
137
  "hyper",
138
- "ring",
139
  "time",
140
  "tokio",
141
  "tower",
@@ -541,9 +541,9 @@ dependencies = [
541
 
542
  [[package]]
543
  name = "base64"
544
- version = "0.21.4"
545
  source = "registry+https://github.com/rust-lang/crates.io-index"
546
- checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2"
547
 
548
  [[package]]
549
  name = "base64-simd"
@@ -663,9 +663,9 @@ dependencies = [
663
 
664
  [[package]]
665
  name = "clap"
666
- version = "4.4.6"
667
  source = "registry+https://github.com/rust-lang/crates.io-index"
668
- checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956"
669
  dependencies = [
670
  "clap_builder",
671
  "clap_derive",
@@ -673,9 +673,9 @@ dependencies = [
673
 
674
  [[package]]
675
  name = "clap_builder"
676
- version = "4.4.6"
677
  source = "registry+https://github.com/rust-lang/crates.io-index"
678
- checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45"
679
  dependencies = [
680
  "anstream",
681
  "anstyle",
@@ -685,21 +685,21 @@ dependencies = [
685
 
686
  [[package]]
687
  name = "clap_derive"
688
- version = "4.4.2"
689
  source = "registry+https://github.com/rust-lang/crates.io-index"
690
- checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873"
691
  dependencies = [
692
  "heck",
693
  "proc-macro2",
694
  "quote",
695
- "syn 2.0.38",
696
  ]
697
 
698
  [[package]]
699
  name = "clap_lex"
700
- version = "0.5.1"
701
  source = "registry+https://github.com/rust-lang/crates.io-index"
702
- checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
703
 
704
  [[package]]
705
  name = "colorchoice"
@@ -725,9 +725,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
725
 
726
  [[package]]
727
  name = "cpufeatures"
728
- version = "0.2.9"
729
  source = "registry+https://github.com/rust-lang/crates.io-index"
730
- checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
731
  dependencies = [
732
  "libc",
733
  ]
@@ -791,9 +791,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
791
 
792
  [[package]]
793
  name = "errno"
794
- version = "0.3.5"
795
  source = "registry+https://github.com/rust-lang/crates.io-index"
796
- checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860"
797
  dependencies = [
798
  "libc",
799
  "windows-sys",
@@ -822,47 +822,47 @@ dependencies = [
822
 
823
  [[package]]
824
  name = "futures-channel"
825
- version = "0.3.28"
826
  source = "registry+https://github.com/rust-lang/crates.io-index"
827
- checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
828
  dependencies = [
829
  "futures-core",
830
  ]
831
 
832
  [[package]]
833
  name = "futures-core"
834
- version = "0.3.28"
835
  source = "registry+https://github.com/rust-lang/crates.io-index"
836
- checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
837
 
838
  [[package]]
839
  name = "futures-macro"
840
- version = "0.3.28"
841
  source = "registry+https://github.com/rust-lang/crates.io-index"
842
- checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
843
  dependencies = [
844
  "proc-macro2",
845
  "quote",
846
- "syn 2.0.38",
847
  ]
848
 
849
  [[package]]
850
  name = "futures-sink"
851
- version = "0.3.28"
852
  source = "registry+https://github.com/rust-lang/crates.io-index"
853
- checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
854
 
855
  [[package]]
856
  name = "futures-task"
857
- version = "0.3.28"
858
  source = "registry+https://github.com/rust-lang/crates.io-index"
859
- checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
860
 
861
  [[package]]
862
  name = "futures-util"
863
- version = "0.3.28"
864
  source = "registry+https://github.com/rust-lang/crates.io-index"
865
- checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
866
  dependencies = [
867
  "futures-core",
868
  "futures-macro",
@@ -885,9 +885,9 @@ dependencies = [
885
 
886
  [[package]]
887
  name = "getrandom"
888
- version = "0.2.10"
889
  source = "registry+https://github.com/rust-lang/crates.io-index"
890
- checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
891
  dependencies = [
892
  "cfg-if",
893
  "libc",
@@ -933,9 +933,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
933
 
934
  [[package]]
935
  name = "hashbrown"
936
- version = "0.14.1"
937
  source = "registry+https://github.com/rust-lang/crates.io-index"
938
- checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12"
939
 
940
  [[package]]
941
  name = "headers"
@@ -1048,7 +1048,7 @@ dependencies = [
1048
  "httpdate",
1049
  "itoa",
1050
  "pin-project-lite",
1051
- "socket2 0.4.9",
1052
  "tokio",
1053
  "tower-service",
1054
  "tracing",
@@ -1057,9 +1057,9 @@ dependencies = [
1057
 
1058
  [[package]]
1059
  name = "hyper-rustls"
1060
- version = "0.24.1"
1061
  source = "registry+https://github.com/rust-lang/crates.io-index"
1062
- checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97"
1063
  dependencies = [
1064
  "futures-util",
1065
  "http",
@@ -1093,12 +1093,12 @@ dependencies = [
1093
 
1094
  [[package]]
1095
  name = "indexmap"
1096
- version = "2.0.2"
1097
  source = "registry+https://github.com/rust-lang/crates.io-index"
1098
- checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897"
1099
  dependencies = [
1100
  "equivalent",
1101
- "hashbrown 0.14.1",
1102
  ]
1103
 
1104
  [[package]]
@@ -1109,9 +1109,9 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
1109
 
1110
  [[package]]
1111
  name = "js-sys"
1112
- version = "0.3.64"
1113
  source = "registry+https://github.com/rust-lang/crates.io-index"
1114
- checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"
1115
  dependencies = [
1116
  "wasm-bindgen",
1117
  ]
@@ -1130,9 +1130,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
1130
 
1131
  [[package]]
1132
  name = "libc"
1133
- version = "0.2.149"
1134
  source = "registry+https://github.com/rust-lang/crates.io-index"
1135
- checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"
1136
 
1137
  [[package]]
1138
  name = "libloading"
@@ -1205,9 +1205,9 @@ dependencies = [
1205
 
1206
  [[package]]
1207
  name = "mio"
1208
- version = "0.8.8"
1209
  source = "registry+https://github.com/rust-lang/crates.io-index"
1210
- checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
1211
  dependencies = [
1212
  "libc",
1213
  "wasi",
@@ -1348,7 +1348,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
1348
  dependencies = [
1349
  "proc-macro2",
1350
  "quote",
1351
- "syn 2.0.38",
1352
  ]
1353
 
1354
  [[package]]
@@ -1405,7 +1405,7 @@ dependencies = [
1405
  "proc-macro-crate",
1406
  "proc-macro2",
1407
  "quote",
1408
- "syn 2.0.38",
1409
  ]
1410
 
1411
  [[package]]
@@ -1558,12 +1558,26 @@ dependencies = [
1558
  "cc",
1559
  "libc",
1560
  "once_cell",
1561
- "spin",
1562
- "untrusted",
1563
  "web-sys",
1564
  "winapi",
1565
  ]
1566
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1567
  [[package]]
1568
  name = "rustc-demangle"
1569
  version = "0.1.23"
@@ -1587,9 +1601,9 @@ dependencies = [
1587
 
1588
  [[package]]
1589
  name = "rustix"
1590
- version = "0.38.20"
1591
  source = "registry+https://github.com/rust-lang/crates.io-index"
1592
- checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0"
1593
  dependencies = [
1594
  "bitflags 2.4.1",
1595
  "errno",
@@ -1600,12 +1614,12 @@ dependencies = [
1600
 
1601
  [[package]]
1602
  name = "rustls"
1603
- version = "0.21.7"
1604
  source = "registry+https://github.com/rust-lang/crates.io-index"
1605
- checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8"
1606
  dependencies = [
1607
  "log",
1608
- "ring",
1609
  "rustls-webpki",
1610
  "sct",
1611
  ]
@@ -1633,12 +1647,12 @@ dependencies = [
1633
 
1634
  [[package]]
1635
  name = "rustls-webpki"
1636
- version = "0.101.6"
1637
  source = "registry+https://github.com/rust-lang/crates.io-index"
1638
- checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe"
1639
  dependencies = [
1640
- "ring",
1641
- "untrusted",
1642
  ]
1643
 
1644
  [[package]]
@@ -1664,12 +1678,12 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
1664
 
1665
  [[package]]
1666
  name = "sct"
1667
- version = "0.7.0"
1668
  source = "registry+https://github.com/rust-lang/crates.io-index"
1669
- checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
1670
  dependencies = [
1671
- "ring",
1672
- "untrusted",
1673
  ]
1674
 
1675
  [[package]]
@@ -1703,29 +1717,29 @@ checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
1703
 
1704
  [[package]]
1705
  name = "serde"
1706
- version = "1.0.189"
1707
  source = "registry+https://github.com/rust-lang/crates.io-index"
1708
- checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537"
1709
  dependencies = [
1710
  "serde_derive",
1711
  ]
1712
 
1713
  [[package]]
1714
  name = "serde_derive"
1715
- version = "1.0.189"
1716
  source = "registry+https://github.com/rust-lang/crates.io-index"
1717
- checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5"
1718
  dependencies = [
1719
  "proc-macro2",
1720
  "quote",
1721
- "syn 2.0.38",
1722
  ]
1723
 
1724
  [[package]]
1725
  name = "serde_json"
1726
- version = "1.0.107"
1727
  source = "registry+https://github.com/rust-lang/crates.io-index"
1728
- checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
1729
  dependencies = [
1730
  "itoa",
1731
  "ryu",
@@ -1746,11 +1760,11 @@ dependencies = [
1746
 
1747
  [[package]]
1748
  name = "serde_yaml"
1749
- version = "0.9.25"
1750
  source = "registry+https://github.com/rust-lang/crates.io-index"
1751
- checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574"
1752
  dependencies = [
1753
- "indexmap 2.0.2",
1754
  "itoa",
1755
  "ryu",
1756
  "serde",
@@ -1794,15 +1808,6 @@ version = "1.2.0"
1794
  source = "registry+https://github.com/rust-lang/crates.io-index"
1795
  checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380"
1796
 
1797
- [[package]]
1798
- name = "signal-hook-registry"
1799
- version = "1.4.1"
1800
- source = "registry+https://github.com/rust-lang/crates.io-index"
1801
- checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
1802
- dependencies = [
1803
- "libc",
1804
- ]
1805
-
1806
  [[package]]
1807
  name = "slab"
1808
  version = "0.4.9"
@@ -1820,9 +1825,9 @@ checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
1820
 
1821
  [[package]]
1822
  name = "socket2"
1823
- version = "0.4.9"
1824
  source = "registry+https://github.com/rust-lang/crates.io-index"
1825
- checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
1826
  dependencies = [
1827
  "libc",
1828
  "winapi",
@@ -1830,9 +1835,9 @@ dependencies = [
1830
 
1831
  [[package]]
1832
  name = "socket2"
1833
- version = "0.5.4"
1834
  source = "registry+https://github.com/rust-lang/crates.io-index"
1835
- checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e"
1836
  dependencies = [
1837
  "libc",
1838
  "windows-sys",
@@ -1844,6 +1849,12 @@ version = "0.5.2"
1844
  source = "registry+https://github.com/rust-lang/crates.io-index"
1845
  checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
1846
 
 
 
 
 
 
 
1847
  [[package]]
1848
  name = "strsim"
1849
  version = "0.10.0"
@@ -1869,9 +1880,9 @@ dependencies = [
1869
 
1870
  [[package]]
1871
  name = "syn"
1872
- version = "2.0.38"
1873
  source = "registry+https://github.com/rust-lang/crates.io-index"
1874
- checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"
1875
  dependencies = [
1876
  "proc-macro2",
1877
  "quote",
@@ -1880,22 +1891,22 @@ dependencies = [
1880
 
1881
  [[package]]
1882
  name = "thiserror"
1883
- version = "1.0.49"
1884
  source = "registry+https://github.com/rust-lang/crates.io-index"
1885
- checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4"
1886
  dependencies = [
1887
  "thiserror-impl",
1888
  ]
1889
 
1890
  [[package]]
1891
  name = "thiserror-impl"
1892
- version = "1.0.49"
1893
  source = "registry+https://github.com/rust-lang/crates.io-index"
1894
- checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc"
1895
  dependencies = [
1896
  "proc-macro2",
1897
  "quote",
1898
- "syn 2.0.38",
1899
  ]
1900
 
1901
  [[package]]
@@ -1962,10 +1973,8 @@ dependencies = [
1962
  "libc",
1963
  "mio",
1964
  "num_cpus",
1965
- "parking_lot",
1966
  "pin-project-lite",
1967
- "signal-hook-registry",
1968
- "socket2 0.5.4",
1969
  "tokio-macros",
1970
  "windows-sys",
1971
  ]
@@ -1978,7 +1987,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
1978
  dependencies = [
1979
  "proc-macro2",
1980
  "quote",
1981
- "syn 2.0.38",
1982
  ]
1983
 
1984
  [[package]]
@@ -2016,9 +2025,9 @@ dependencies = [
2016
 
2017
  [[package]]
2018
  name = "tokio-util"
2019
- version = "0.7.9"
2020
  source = "registry+https://github.com/rust-lang/crates.io-index"
2021
- checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d"
2022
  dependencies = [
2023
  "bytes",
2024
  "futures-core",
@@ -2030,9 +2039,9 @@ dependencies = [
2030
 
2031
  [[package]]
2032
  name = "toml_datetime"
2033
- version = "0.6.3"
2034
  source = "registry+https://github.com/rust-lang/crates.io-index"
2035
- checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
2036
 
2037
  [[package]]
2038
  name = "toml_edit"
@@ -2040,7 +2049,7 @@ version = "0.19.15"
2040
  source = "registry+https://github.com/rust-lang/crates.io-index"
2041
  checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
2042
  dependencies = [
2043
- "indexmap 2.0.2",
2044
  "toml_datetime",
2045
  "winnow",
2046
  ]
@@ -2093,7 +2102,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
2093
  dependencies = [
2094
  "proc-macro2",
2095
  "quote",
2096
- "syn 2.0.38",
2097
  ]
2098
 
2099
  [[package]]
@@ -2108,12 +2117,12 @@ dependencies = [
2108
 
2109
  [[package]]
2110
  name = "tracing-log"
2111
- version = "0.1.3"
2112
  source = "registry+https://github.com/rust-lang/crates.io-index"
2113
- checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
2114
  dependencies = [
2115
- "lazy_static",
2116
  "log",
 
2117
  "tracing-core",
2118
  ]
2119
 
@@ -2213,6 +2222,12 @@ version = "0.7.1"
2213
  source = "registry+https://github.com/rust-lang/crates.io-index"
2214
  checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
2215
 
 
 
 
 
 
 
2216
  [[package]]
2217
  name = "url"
2218
  version = "2.4.1"
@@ -2244,9 +2259,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
2244
 
2245
  [[package]]
2246
  name = "uuid"
2247
- version = "1.4.1"
2248
  source = "registry+https://github.com/rust-lang/crates.io-index"
2249
- checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d"
2250
 
2251
  [[package]]
2252
  name = "valuable"
@@ -2283,9 +2298,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
2283
 
2284
  [[package]]
2285
  name = "wasm-bindgen"
2286
- version = "0.2.87"
2287
  source = "registry+https://github.com/rust-lang/crates.io-index"
2288
- checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
2289
  dependencies = [
2290
  "cfg-if",
2291
  "wasm-bindgen-macro",
@@ -2293,24 +2308,24 @@ dependencies = [
2293
 
2294
  [[package]]
2295
  name = "wasm-bindgen-backend"
2296
- version = "0.2.87"
2297
  source = "registry+https://github.com/rust-lang/crates.io-index"
2298
- checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
2299
  dependencies = [
2300
  "bumpalo",
2301
  "log",
2302
  "once_cell",
2303
  "proc-macro2",
2304
  "quote",
2305
- "syn 2.0.38",
2306
  "wasm-bindgen-shared",
2307
  ]
2308
 
2309
  [[package]]
2310
  name = "wasm-bindgen-macro"
2311
- version = "0.2.87"
2312
  source = "registry+https://github.com/rust-lang/crates.io-index"
2313
- checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
2314
  dependencies = [
2315
  "quote",
2316
  "wasm-bindgen-macro-support",
@@ -2318,28 +2333,28 @@ dependencies = [
2318
 
2319
  [[package]]
2320
  name = "wasm-bindgen-macro-support"
2321
- version = "0.2.87"
2322
  source = "registry+https://github.com/rust-lang/crates.io-index"
2323
- checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
2324
  dependencies = [
2325
  "proc-macro2",
2326
  "quote",
2327
- "syn 2.0.38",
2328
  "wasm-bindgen-backend",
2329
  "wasm-bindgen-shared",
2330
  ]
2331
 
2332
  [[package]]
2333
  name = "wasm-bindgen-shared"
2334
- version = "0.2.87"
2335
  source = "registry+https://github.com/rust-lang/crates.io-index"
2336
- checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
2337
 
2338
  [[package]]
2339
  name = "web-sys"
2340
- version = "0.3.64"
2341
  source = "registry+https://github.com/rust-lang/crates.io-index"
2342
- checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b"
2343
  dependencies = [
2344
  "js-sys",
2345
  "wasm-bindgen",
@@ -2466,9 +2481,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
2466
 
2467
  [[package]]
2468
  name = "winnow"
2469
- version = "0.5.17"
2470
  source = "registry+https://github.com/rust-lang/crates.io-index"
2471
- checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c"
2472
  dependencies = [
2473
  "memchr",
2474
  ]
 
93
  dependencies = [
94
  "proc-macro2",
95
  "quote",
96
+ "syn 2.0.39",
97
  ]
98
 
99
  [[package]]
 
104
  dependencies = [
105
  "proc-macro2",
106
  "quote",
107
+ "syn 2.0.39",
108
  ]
109
 
110
  [[package]]
 
135
  "hex",
136
  "http",
137
  "hyper",
138
+ "ring 0.16.20",
139
  "time",
140
  "tokio",
141
  "tower",
 
541
 
542
  [[package]]
543
  name = "base64"
544
+ version = "0.21.5"
545
  source = "registry+https://github.com/rust-lang/crates.io-index"
546
+ checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9"
547
 
548
  [[package]]
549
  name = "base64-simd"
 
663
 
664
  [[package]]
665
  name = "clap"
666
+ version = "4.4.7"
667
  source = "registry+https://github.com/rust-lang/crates.io-index"
668
+ checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b"
669
  dependencies = [
670
  "clap_builder",
671
  "clap_derive",
 
673
 
674
  [[package]]
675
  name = "clap_builder"
676
+ version = "4.4.7"
677
  source = "registry+https://github.com/rust-lang/crates.io-index"
678
+ checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663"
679
  dependencies = [
680
  "anstream",
681
  "anstyle",
 
685
 
686
  [[package]]
687
  name = "clap_derive"
688
+ version = "4.4.7"
689
  source = "registry+https://github.com/rust-lang/crates.io-index"
690
+ checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
691
  dependencies = [
692
  "heck",
693
  "proc-macro2",
694
  "quote",
695
+ "syn 2.0.39",
696
  ]
697
 
698
  [[package]]
699
  name = "clap_lex"
700
+ version = "0.6.0"
701
  source = "registry+https://github.com/rust-lang/crates.io-index"
702
+ checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
703
 
704
  [[package]]
705
  name = "colorchoice"
 
725
 
726
  [[package]]
727
  name = "cpufeatures"
728
+ version = "0.2.11"
729
  source = "registry+https://github.com/rust-lang/crates.io-index"
730
+ checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0"
731
  dependencies = [
732
  "libc",
733
  ]
 
791
 
792
  [[package]]
793
  name = "errno"
794
+ version = "0.3.6"
795
  source = "registry+https://github.com/rust-lang/crates.io-index"
796
+ checksum = "7c18ee0ed65a5f1f81cac6b1d213b69c35fa47d4252ad41f1486dbd8226fe36e"
797
  dependencies = [
798
  "libc",
799
  "windows-sys",
 
822
 
823
  [[package]]
824
  name = "futures-channel"
825
+ version = "0.3.29"
826
  source = "registry+https://github.com/rust-lang/crates.io-index"
827
+ checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb"
828
  dependencies = [
829
  "futures-core",
830
  ]
831
 
832
  [[package]]
833
  name = "futures-core"
834
+ version = "0.3.29"
835
  source = "registry+https://github.com/rust-lang/crates.io-index"
836
+ checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
837
 
838
  [[package]]
839
  name = "futures-macro"
840
+ version = "0.3.29"
841
  source = "registry+https://github.com/rust-lang/crates.io-index"
842
+ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
843
  dependencies = [
844
  "proc-macro2",
845
  "quote",
846
+ "syn 2.0.39",
847
  ]
848
 
849
  [[package]]
850
  name = "futures-sink"
851
+ version = "0.3.29"
852
  source = "registry+https://github.com/rust-lang/crates.io-index"
853
+ checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"
854
 
855
  [[package]]
856
  name = "futures-task"
857
+ version = "0.3.29"
858
  source = "registry+https://github.com/rust-lang/crates.io-index"
859
+ checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
860
 
861
  [[package]]
862
  name = "futures-util"
863
+ version = "0.3.29"
864
  source = "registry+https://github.com/rust-lang/crates.io-index"
865
+ checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
866
  dependencies = [
867
  "futures-core",
868
  "futures-macro",
 
885
 
886
  [[package]]
887
  name = "getrandom"
888
+ version = "0.2.11"
889
  source = "registry+https://github.com/rust-lang/crates.io-index"
890
+ checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
891
  dependencies = [
892
  "cfg-if",
893
  "libc",
 
933
 
934
  [[package]]
935
  name = "hashbrown"
936
+ version = "0.14.2"
937
  source = "registry+https://github.com/rust-lang/crates.io-index"
938
+ checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156"
939
 
940
  [[package]]
941
  name = "headers"
 
1048
  "httpdate",
1049
  "itoa",
1050
  "pin-project-lite",
1051
+ "socket2 0.4.10",
1052
  "tokio",
1053
  "tower-service",
1054
  "tracing",
 
1057
 
1058
  [[package]]
1059
  name = "hyper-rustls"
1060
+ version = "0.24.2"
1061
  source = "registry+https://github.com/rust-lang/crates.io-index"
1062
+ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590"
1063
  dependencies = [
1064
  "futures-util",
1065
  "http",
 
1093
 
1094
  [[package]]
1095
  name = "indexmap"
1096
+ version = "2.1.0"
1097
  source = "registry+https://github.com/rust-lang/crates.io-index"
1098
+ checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
1099
  dependencies = [
1100
  "equivalent",
1101
+ "hashbrown 0.14.2",
1102
  ]
1103
 
1104
  [[package]]
 
1109
 
1110
  [[package]]
1111
  name = "js-sys"
1112
+ version = "0.3.65"
1113
  source = "registry+https://github.com/rust-lang/crates.io-index"
1114
+ checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8"
1115
  dependencies = [
1116
  "wasm-bindgen",
1117
  ]
 
1130
 
1131
  [[package]]
1132
  name = "libc"
1133
+ version = "0.2.150"
1134
  source = "registry+https://github.com/rust-lang/crates.io-index"
1135
+ checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
1136
 
1137
  [[package]]
1138
  name = "libloading"
 
1205
 
1206
  [[package]]
1207
  name = "mio"
1208
+ version = "0.8.9"
1209
  source = "registry+https://github.com/rust-lang/crates.io-index"
1210
+ checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0"
1211
  dependencies = [
1212
  "libc",
1213
  "wasi",
 
1348
  dependencies = [
1349
  "proc-macro2",
1350
  "quote",
1351
+ "syn 2.0.39",
1352
  ]
1353
 
1354
  [[package]]
 
1405
  "proc-macro-crate",
1406
  "proc-macro2",
1407
  "quote",
1408
+ "syn 2.0.39",
1409
  ]
1410
 
1411
  [[package]]
 
1558
  "cc",
1559
  "libc",
1560
  "once_cell",
1561
+ "spin 0.5.2",
1562
+ "untrusted 0.7.1",
1563
  "web-sys",
1564
  "winapi",
1565
  ]
1566
 
1567
+ [[package]]
1568
+ name = "ring"
1569
+ version = "0.17.5"
1570
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1571
+ checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b"
1572
+ dependencies = [
1573
+ "cc",
1574
+ "getrandom",
1575
+ "libc",
1576
+ "spin 0.9.8",
1577
+ "untrusted 0.9.0",
1578
+ "windows-sys",
1579
+ ]
1580
+
1581
  [[package]]
1582
  name = "rustc-demangle"
1583
  version = "0.1.23"
 
1601
 
1602
  [[package]]
1603
  name = "rustix"
1604
+ version = "0.38.21"
1605
  source = "registry+https://github.com/rust-lang/crates.io-index"
1606
+ checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3"
1607
  dependencies = [
1608
  "bitflags 2.4.1",
1609
  "errno",
 
1614
 
1615
  [[package]]
1616
  name = "rustls"
1617
+ version = "0.21.8"
1618
  source = "registry+https://github.com/rust-lang/crates.io-index"
1619
+ checksum = "446e14c5cda4f3f30fe71863c34ec70f5ac79d6087097ad0bb433e1be5edf04c"
1620
  dependencies = [
1621
  "log",
1622
+ "ring 0.17.5",
1623
  "rustls-webpki",
1624
  "sct",
1625
  ]
 
1647
 
1648
  [[package]]
1649
  name = "rustls-webpki"
1650
+ version = "0.101.7"
1651
  source = "registry+https://github.com/rust-lang/crates.io-index"
1652
+ checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765"
1653
  dependencies = [
1654
+ "ring 0.17.5",
1655
+ "untrusted 0.9.0",
1656
  ]
1657
 
1658
  [[package]]
 
1678
 
1679
  [[package]]
1680
  name = "sct"
1681
+ version = "0.7.1"
1682
  source = "registry+https://github.com/rust-lang/crates.io-index"
1683
+ checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
1684
  dependencies = [
1685
+ "ring 0.17.5",
1686
+ "untrusted 0.9.0",
1687
  ]
1688
 
1689
  [[package]]
 
1717
 
1718
  [[package]]
1719
  name = "serde"
1720
+ version = "1.0.192"
1721
  source = "registry+https://github.com/rust-lang/crates.io-index"
1722
+ checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001"
1723
  dependencies = [
1724
  "serde_derive",
1725
  ]
1726
 
1727
  [[package]]
1728
  name = "serde_derive"
1729
+ version = "1.0.192"
1730
  source = "registry+https://github.com/rust-lang/crates.io-index"
1731
+ checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1"
1732
  dependencies = [
1733
  "proc-macro2",
1734
  "quote",
1735
+ "syn 2.0.39",
1736
  ]
1737
 
1738
  [[package]]
1739
  name = "serde_json"
1740
+ version = "1.0.108"
1741
  source = "registry+https://github.com/rust-lang/crates.io-index"
1742
+ checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
1743
  dependencies = [
1744
  "itoa",
1745
  "ryu",
 
1760
 
1761
  [[package]]
1762
  name = "serde_yaml"
1763
+ version = "0.9.27"
1764
  source = "registry+https://github.com/rust-lang/crates.io-index"
1765
+ checksum = "3cc7a1570e38322cfe4154732e5110f887ea57e22b76f4bfd32b5bdd3368666c"
1766
  dependencies = [
1767
+ "indexmap 2.1.0",
1768
  "itoa",
1769
  "ryu",
1770
  "serde",
 
1808
  source = "registry+https://github.com/rust-lang/crates.io-index"
1809
  checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380"
1810
 
 
 
 
 
 
 
 
 
 
1811
  [[package]]
1812
  name = "slab"
1813
  version = "0.4.9"
 
1825
 
1826
  [[package]]
1827
  name = "socket2"
1828
+ version = "0.4.10"
1829
  source = "registry+https://github.com/rust-lang/crates.io-index"
1830
+ checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d"
1831
  dependencies = [
1832
  "libc",
1833
  "winapi",
 
1835
 
1836
  [[package]]
1837
  name = "socket2"
1838
+ version = "0.5.5"
1839
  source = "registry+https://github.com/rust-lang/crates.io-index"
1840
+ checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
1841
  dependencies = [
1842
  "libc",
1843
  "windows-sys",
 
1849
  source = "registry+https://github.com/rust-lang/crates.io-index"
1850
  checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
1851
 
1852
+ [[package]]
1853
+ name = "spin"
1854
+ version = "0.9.8"
1855
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1856
+ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
1857
+
1858
  [[package]]
1859
  name = "strsim"
1860
  version = "0.10.0"
 
1880
 
1881
  [[package]]
1882
  name = "syn"
1883
+ version = "2.0.39"
1884
  source = "registry+https://github.com/rust-lang/crates.io-index"
1885
+ checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
1886
  dependencies = [
1887
  "proc-macro2",
1888
  "quote",
 
1891
 
1892
  [[package]]
1893
  name = "thiserror"
1894
+ version = "1.0.50"
1895
  source = "registry+https://github.com/rust-lang/crates.io-index"
1896
+ checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
1897
  dependencies = [
1898
  "thiserror-impl",
1899
  ]
1900
 
1901
  [[package]]
1902
  name = "thiserror-impl"
1903
+ version = "1.0.50"
1904
  source = "registry+https://github.com/rust-lang/crates.io-index"
1905
+ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
1906
  dependencies = [
1907
  "proc-macro2",
1908
  "quote",
1909
+ "syn 2.0.39",
1910
  ]
1911
 
1912
  [[package]]
 
1973
  "libc",
1974
  "mio",
1975
  "num_cpus",
 
1976
  "pin-project-lite",
1977
+ "socket2 0.5.5",
 
1978
  "tokio-macros",
1979
  "windows-sys",
1980
  ]
 
1987
  dependencies = [
1988
  "proc-macro2",
1989
  "quote",
1990
+ "syn 2.0.39",
1991
  ]
1992
 
1993
  [[package]]
 
2025
 
2026
  [[package]]
2027
  name = "tokio-util"
2028
+ version = "0.7.10"
2029
  source = "registry+https://github.com/rust-lang/crates.io-index"
2030
+ checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15"
2031
  dependencies = [
2032
  "bytes",
2033
  "futures-core",
 
2039
 
2040
  [[package]]
2041
  name = "toml_datetime"
2042
+ version = "0.6.5"
2043
  source = "registry+https://github.com/rust-lang/crates.io-index"
2044
+ checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
2045
 
2046
  [[package]]
2047
  name = "toml_edit"
 
2049
  source = "registry+https://github.com/rust-lang/crates.io-index"
2050
  checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
2051
  dependencies = [
2052
+ "indexmap 2.1.0",
2053
  "toml_datetime",
2054
  "winnow",
2055
  ]
 
2102
  dependencies = [
2103
  "proc-macro2",
2104
  "quote",
2105
+ "syn 2.0.39",
2106
  ]
2107
 
2108
  [[package]]
 
2117
 
2118
  [[package]]
2119
  name = "tracing-log"
2120
+ version = "0.1.4"
2121
  source = "registry+https://github.com/rust-lang/crates.io-index"
2122
+ checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2"
2123
  dependencies = [
 
2124
  "log",
2125
+ "once_cell",
2126
  "tracing-core",
2127
  ]
2128
 
 
2222
  source = "registry+https://github.com/rust-lang/crates.io-index"
2223
  checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
2224
 
2225
+ [[package]]
2226
+ name = "untrusted"
2227
+ version = "0.9.0"
2228
+ source = "registry+https://github.com/rust-lang/crates.io-index"
2229
+ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
2230
+
2231
  [[package]]
2232
  name = "url"
2233
  version = "2.4.1"
 
2259
 
2260
  [[package]]
2261
  name = "uuid"
2262
+ version = "1.5.0"
2263
  source = "registry+https://github.com/rust-lang/crates.io-index"
2264
+ checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc"
2265
 
2266
  [[package]]
2267
  name = "valuable"
 
2298
 
2299
  [[package]]
2300
  name = "wasm-bindgen"
2301
+ version = "0.2.88"
2302
  source = "registry+https://github.com/rust-lang/crates.io-index"
2303
+ checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce"
2304
  dependencies = [
2305
  "cfg-if",
2306
  "wasm-bindgen-macro",
 
2308
 
2309
  [[package]]
2310
  name = "wasm-bindgen-backend"
2311
+ version = "0.2.88"
2312
  source = "registry+https://github.com/rust-lang/crates.io-index"
2313
+ checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217"
2314
  dependencies = [
2315
  "bumpalo",
2316
  "log",
2317
  "once_cell",
2318
  "proc-macro2",
2319
  "quote",
2320
+ "syn 2.0.39",
2321
  "wasm-bindgen-shared",
2322
  ]
2323
 
2324
  [[package]]
2325
  name = "wasm-bindgen-macro"
2326
+ version = "0.2.88"
2327
  source = "registry+https://github.com/rust-lang/crates.io-index"
2328
+ checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2"
2329
  dependencies = [
2330
  "quote",
2331
  "wasm-bindgen-macro-support",
 
2333
 
2334
  [[package]]
2335
  name = "wasm-bindgen-macro-support"
2336
+ version = "0.2.88"
2337
  source = "registry+https://github.com/rust-lang/crates.io-index"
2338
+ checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907"
2339
  dependencies = [
2340
  "proc-macro2",
2341
  "quote",
2342
+ "syn 2.0.39",
2343
  "wasm-bindgen-backend",
2344
  "wasm-bindgen-shared",
2345
  ]
2346
 
2347
  [[package]]
2348
  name = "wasm-bindgen-shared"
2349
+ version = "0.2.88"
2350
  source = "registry+https://github.com/rust-lang/crates.io-index"
2351
+ checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b"
2352
 
2353
  [[package]]
2354
  name = "web-sys"
2355
+ version = "0.3.65"
2356
  source = "registry+https://github.com/rust-lang/crates.io-index"
2357
+ checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85"
2358
  dependencies = [
2359
  "js-sys",
2360
  "wasm-bindgen",
 
2481
 
2482
  [[package]]
2483
  name = "winnow"
2484
+ version = "0.5.19"
2485
  source = "registry+https://github.com/rust-lang/crates.io-index"
2486
+ checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b"
2487
  dependencies = [
2488
  "memchr",
2489
  ]
Cargo.toml CHANGED
@@ -4,19 +4,19 @@ version = "0.1.0"
4
  edition = "2021"
5
 
6
  [dependencies]
7
- aws-config= { version = "0.56.1" }
8
- aws-sdk-transcribestreaming= { version = "0.34" }
9
  aws-sdk-translate = "0.34"
10
  aws-sdk-polly = "0.34"
11
- clap = { version = "4.4" , features = ["derive"]}
12
- tokio = { version = "1.33" , features = ["full"] }
13
  tokio-stream = "0.1"
14
  async-stream = "0.3"
15
  futures-util = "0.3"
16
  serde = { version = "1.0", features = ["derive"] }
17
- serde_json = { version = "1.0" }
18
  serde_yaml = "0.9"
19
- whisper-rs = { version = "0.8" }
20
  whisper-rs-sys = "0.6"
21
  tracing = "0.1"
22
  tracing-subscriber = "0.3"
 
4
  edition = "2021"
5
 
6
  [dependencies]
7
+ aws-config = "0.56"
8
+ aws-sdk-transcribestreaming = "0.34"
9
  aws-sdk-translate = "0.34"
10
  aws-sdk-polly = "0.34"
11
+ clap = { version = "4.4", features = ["derive"] }
12
+ tokio = { version = "1.33", features = ["macros", "rt-multi-thread", "sync"] }
13
  tokio-stream = "0.1"
14
  async-stream = "0.3"
15
  futures-util = "0.3"
16
  serde = { version = "1.0", features = ["derive"] }
17
+ serde_json = "1.0"
18
  serde_yaml = "0.9"
19
+ whisper-rs = "0.8"
20
  whisper-rs-sys = "0.6"
21
  tracing = "0.1"
22
  tracing-subscriber = "0.3"
src/config.rs CHANGED
@@ -1,7 +1,7 @@
 
 
1
  use std::ffi::c_int;
2
  use std::net::IpAddr;
3
- use lazy_static::lazy_static;
4
- use serde::{Deserialize};
5
  use whisper_rs::FullParams;
6
 
7
  #[derive(Debug)]
@@ -12,9 +12,9 @@ pub enum Error {
12
 
13
  pub(crate) fn load_config() -> Result<Config, Error> {
14
  let config_str = std::fs::read_to_string("config.yaml").map_err(|e| Error::IoError(e))?;
15
- let config: Config = serde_yaml::from_str(config_str.as_str())
16
- .map_err(|e| Error::ConfigError(e))?;
17
- return Ok(config)
18
  }
19
 
20
  lazy_static! {
@@ -49,7 +49,7 @@ pub(crate) struct WhisperParams {
49
  pub(crate) language: Option<String>,
50
  }
51
 
52
- const NONE: [c_int;0] = [];
53
 
54
  impl WhisperParams {
55
  pub(crate) fn to_full_params<'a, 'b>(&'a self, tokens: &'b [c_int]) -> FullParams<'a, 'b> {
@@ -63,7 +63,9 @@ impl WhisperParams {
63
  param.set_max_tokens(self.max_tokens as i32);
64
  let lang = self.language.as_ref().map(|s| s.as_str());
65
  param.set_language(lang);
66
- let num_cpus = std::thread::available_parallelism().map(|c| c.get()).unwrap_or(4);
 
 
67
  param.set_n_threads(self.n_threads.unwrap_or(num_cpus) as c_int);
68
  param.set_audio_ctx(self.audio_ctx as i32);
69
  param.set_speed_up(self.speed_up);
@@ -89,8 +91,11 @@ pub struct Config {
89
  mod tests {
90
  #[tokio::test]
91
  async fn load() {
92
- let config_str = tokio::fs::read_to_string("config.yaml").await.expect("failed to read config file");
93
- let params: crate::config::Config = serde_yaml::from_str(config_str.as_str()).expect("failed to parse config file");
 
 
 
94
  println!("{:?}", params);
95
  }
96
- }
 
1
+ use lazy_static::lazy_static;
2
+ use serde::Deserialize;
3
  use std::ffi::c_int;
4
  use std::net::IpAddr;
 
 
5
  use whisper_rs::FullParams;
6
 
7
  #[derive(Debug)]
 
12
 
13
  pub(crate) fn load_config() -> Result<Config, Error> {
14
  let config_str = std::fs::read_to_string("config.yaml").map_err(|e| Error::IoError(e))?;
15
+ let config: Config =
16
+ serde_yaml::from_str(config_str.as_str()).map_err(|e| Error::ConfigError(e))?;
17
+ return Ok(config);
18
  }
19
 
20
  lazy_static! {
 
49
  pub(crate) language: Option<String>,
50
  }
51
 
52
+ const NONE: [c_int; 0] = [];
53
 
54
  impl WhisperParams {
55
  pub(crate) fn to_full_params<'a, 'b>(&'a self, tokens: &'b [c_int]) -> FullParams<'a, 'b> {
 
63
  param.set_max_tokens(self.max_tokens as i32);
64
  let lang = self.language.as_ref().map(|s| s.as_str());
65
  param.set_language(lang);
66
+ let num_cpus = std::thread::available_parallelism()
67
+ .map(|c| c.get())
68
+ .unwrap_or(4);
69
  param.set_n_threads(self.n_threads.unwrap_or(num_cpus) as c_int);
70
  param.set_audio_ctx(self.audio_ctx as i32);
71
  param.set_speed_up(self.speed_up);
 
91
  mod tests {
92
  #[tokio::test]
93
  async fn load() {
94
+ let config_str = tokio::fs::read_to_string("config.yaml")
95
+ .await
96
+ .expect("failed to read config file");
97
+ let params: crate::config::Config =
98
+ serde_yaml::from_str(config_str.as_str()).expect("failed to parse config file");
99
  println!("{:?}", params);
100
  }
101
+ }
src/group.rs CHANGED
@@ -1,21 +1,27 @@
1
  use std::collections::VecDeque;
2
  use std::time::Duration;
3
- use tokio::{select};
4
- use tokio::time::sleep;
5
- use tokio::sync::mpsc::{Receiver, channel};
6
  use tokio::sync::mpsc::error::TryRecvError;
 
 
7
 
8
  pub struct GroupedWithin<I>
9
- where I: 'static + Send {
10
- outlet: Receiver<Vec<I>>
 
 
11
  }
12
 
13
  impl<I> GroupedWithin<I>
14
- where I: 'static + Send {
15
- pub fn new(group_size: usize,
16
- window_time: Duration,
17
- mut inlet: Receiver<Vec<I>>,
18
- buffer: usize) -> Self {
 
 
 
 
19
  let (tx, outlet) = channel::<Vec<I>>(buffer);
20
  tokio::spawn(async move {
21
  let mut window = VecDeque::with_capacity(group_size);
@@ -26,10 +32,10 @@ where I: 'static + Send {
26
  window.extend(c);
27
  if window.len() >= group_size {
28
  let will_send: Vec<I> = window.drain(0..group_size).collect();
29
- return Some(will_send)
30
  }
31
  }
32
- return None
33
  };
34
 
35
  let grouped: Vec<I> = select! {
@@ -45,7 +51,7 @@ where I: 'static + Send {
45
  };
46
 
47
  if grouped.is_empty() {
48
- continue
49
  }
50
 
51
  if let Err(e) = tx.send(grouped).await {
@@ -53,12 +59,10 @@ where I: 'static + Send {
53
  }
54
  }
55
  });
56
- Self {
57
- outlet
58
- }
59
  }
60
 
61
  pub fn next(&mut self) -> Result<Vec<I>, TryRecvError> {
62
  self.outlet.try_recv()
63
  }
64
- }
 
1
  use std::collections::VecDeque;
2
  use std::time::Duration;
3
+ use tokio::select;
 
 
4
  use tokio::sync::mpsc::error::TryRecvError;
5
+ use tokio::sync::mpsc::{channel, Receiver};
6
+ use tokio::time::sleep;
7
 
8
  pub struct GroupedWithin<I>
9
+ where
10
+ I: 'static + Send,
11
+ {
12
+ outlet: Receiver<Vec<I>>,
13
  }
14
 
15
  impl<I> GroupedWithin<I>
16
+ where
17
+ I: 'static + Send,
18
+ {
19
+ pub fn new(
20
+ group_size: usize,
21
+ window_time: Duration,
22
+ mut inlet: Receiver<Vec<I>>,
23
+ buffer: usize,
24
+ ) -> Self {
25
  let (tx, outlet) = channel::<Vec<I>>(buffer);
26
  tokio::spawn(async move {
27
  let mut window = VecDeque::with_capacity(group_size);
 
32
  window.extend(c);
33
  if window.len() >= group_size {
34
  let will_send: Vec<I> = window.drain(0..group_size).collect();
35
+ return Some(will_send);
36
  }
37
  }
38
+ return None;
39
  };
40
 
41
  let grouped: Vec<I> = select! {
 
51
  };
52
 
53
  if grouped.is_empty() {
54
+ continue;
55
  }
56
 
57
  if let Err(e) = tx.send(grouped).await {
 
59
  }
60
  }
61
  });
62
+ Self { outlet }
 
 
63
  }
64
 
65
  pub fn next(&mut self) -> Result<Vec<I>, TryRecvError> {
66
  self.outlet.try_recv()
67
  }
68
+ }
src/lesson.rs CHANGED
@@ -1,19 +1,21 @@
1
- use std::sync::{Arc, Weak};
2
- use tokio::sync::RwLock;
3
- use std::collections::BTreeMap;
4
- use std::error::Error;
5
- use std::fmt::{Display, Formatter};
6
- use std::io::BufRead;
7
  use async_stream::stream;
8
  use aws_config::SdkConfig;
9
  use aws_sdk_polly::primitives::ByteStream;
10
  use aws_sdk_polly::types::{Engine, OutputFormat, SpeechMarkType, VoiceId};
11
  use aws_sdk_transcribestreaming::operation::start_stream_transcription::StartStreamTranscriptionOutput;
12
  use aws_sdk_transcribestreaming::primitives::Blob;
13
- use aws_sdk_transcribestreaming::types::{AudioEvent, AudioStream, LanguageCode, MediaEncoding, TranscriptResultStream};
14
- use futures_util::{Stream, StreamExt, TryStreamExt};
 
15
  use futures_util::future::try_join;
 
16
  use serde::{Deserialize, Serialize};
 
 
 
 
 
 
17
 
18
  use tokio::select;
19
 
@@ -22,7 +24,7 @@ pub struct LessonsManager {
22
  translate_client: aws_sdk_translate::Client,
23
  polly_client: aws_sdk_polly::Client,
24
  transcript_client: aws_sdk_transcribestreaming::Client,
25
- lessons: Arc<RwLock<BTreeMap<u32, Lesson>>>
26
  }
27
 
28
  impl LessonsManager {
@@ -34,13 +36,11 @@ impl LessonsManager {
34
  translate_client,
35
  polly_client,
36
  transcript_client,
37
- lessons: Arc::new(RwLock::new(BTreeMap::new()))
38
  }
39
  }
40
 
41
- pub(crate) async fn create_lesson(&self,
42
- id: u32,
43
- speaker_lang: LanguageCode) -> Lesson {
44
  let mut map = self.lessons.write().await;
45
  let lesson: Lesson = InnerLesson::new(self.clone(), speaker_lang).into();
46
  map.insert(id, lesson.clone());
@@ -55,7 +55,7 @@ impl LessonsManager {
55
 
56
  #[derive(Clone, Debug)]
57
  pub(crate) struct Lesson {
58
- inner: Arc<InnerLesson>
59
  }
60
 
61
  impl Lesson {
@@ -71,10 +71,7 @@ impl Lesson {
71
  if let Some(lang_lesson) = map.get(&lang).and_then(|weak| weak.upgrade()) {
72
  lang_lesson.into()
73
  } else {
74
- let lang_lesson = LangLesson::new(
75
- self.clone(),
76
- lang.clone(),
77
- );
78
  map.insert(lang.clone(), Arc::downgrade(&lang_lesson.inner));
79
  lang_lesson
80
  }
@@ -93,7 +90,7 @@ impl Lesson {
93
  impl From<InnerLesson> for Lesson {
94
  fn from(inner: InnerLesson) -> Self {
95
  Lesson {
96
- inner: Arc::new(inner)
97
  }
98
  }
99
  }
@@ -109,10 +106,7 @@ struct InnerLesson {
109
  }
110
 
111
  impl InnerLesson {
112
- fn new(
113
- parent: LessonsManager,
114
- speaker_lang: LanguageCode
115
- ) -> InnerLesson {
116
  let (speaker_transcript, _) = tokio::sync::broadcast::channel::<String>(128);
117
  let shared_speaker_transcript = speaker_transcript.clone();
118
  let (speaker_voice_channel, mut speaker_voice_rx) = tokio::sync::mpsc::channel(128);
@@ -129,7 +123,7 @@ impl InnerLesson {
129
  };
130
  let output = transcript_client
131
  .start_stream_transcription()
132
- .language_code(shared_speak_lang)//LanguageCode::EnGb
133
  .media_sample_rate_hertz(16000)
134
  .media_encoding(MediaEncoding::Pcm)
135
  .audio_stream(input_stream.into())
@@ -175,7 +169,6 @@ impl Drop for InnerLesson {
175
  }
176
  }
177
 
178
-
179
  struct InnerLangLesson {
180
  parent: Lesson,
181
  translated_tx: tokio::sync::broadcast::Sender<String>,
@@ -193,7 +186,7 @@ impl Drop for InnerLangLesson {
193
 
194
  #[derive(Clone)]
195
  pub(crate) struct LangLesson {
196
- inner: Arc<InnerLangLesson>
197
  }
198
 
199
  impl LangLesson {
@@ -205,24 +198,19 @@ impl LangLesson {
205
  impl From<InnerLangLesson> for LangLesson {
206
  fn from(inner: InnerLangLesson) -> Self {
207
  LangLesson {
208
- inner: Arc::new(inner)
209
  }
210
  }
211
  }
212
 
213
  impl From<Arc<InnerLangLesson>> for LangLesson {
214
  fn from(inner: Arc<InnerLangLesson>) -> Self {
215
- LangLesson {
216
- inner
217
- }
218
  }
219
  }
220
 
221
  impl LangLesson {
222
- fn new(
223
- parent: Lesson,
224
- lang: String,
225
- ) -> Self {
226
  let shared_lang = lang.clone();
227
  let shared_speaker_lang = parent.inner.speaker_lang.clone();
228
  let (translated_tx, _) = tokio::sync::broadcast::channel::<String>(128);
@@ -245,7 +233,7 @@ impl LangLesson {
245
  if let Some(translated) = res.translated_text {
246
  let _ = shared_translated_tx.send(translated);
247
  }
248
- },
249
  Err(e) => {
250
  return Err(e);
251
  }
@@ -268,7 +256,8 @@ impl LangLesson {
268
  translated_tx,
269
  voice_lessons: RwLock::new(BTreeMap::new()),
270
  drop_handler: Some(drop_handler),
271
- }.into()
 
272
  }
273
 
274
  pub(crate) async fn get_or_init(&mut self, voice: VoiceId) -> VoiceLesson {
@@ -284,10 +273,7 @@ impl LangLesson {
284
  if let Some(voice_lesson) = map.get(&voice).and_then(|weak| weak.upgrade()) {
285
  voice_lesson.into()
286
  } else {
287
- let voice_lesson = Arc::new(InnerVoiceLesson::new(
288
- self.clone(),
289
- voice.clone(),
290
- ));
291
  map.insert(voice, Arc::downgrade(&voice_lesson));
292
  voice_lesson.into()
293
  }
@@ -297,7 +283,7 @@ impl LangLesson {
297
 
298
  #[derive(Clone)]
299
  pub(crate) struct VoiceLesson {
300
- inner: Arc<InnerVoiceLesson>
301
  }
302
 
303
  impl VoiceLesson {
@@ -313,16 +299,14 @@ impl VoiceLesson {
313
  impl From<InnerVoiceLesson> for VoiceLesson {
314
  fn from(inner: InnerVoiceLesson) -> Self {
315
  VoiceLesson {
316
- inner: Arc::new(inner)
317
  }
318
  }
319
  }
320
 
321
  impl From<Arc<InnerVoiceLesson>> for VoiceLesson {
322
  fn from(inner: Arc<InnerVoiceLesson>) -> Self {
323
- VoiceLesson {
324
- inner
325
- }
326
  }
327
  }
328
 
@@ -338,10 +322,7 @@ enum Signal {
338
  }
339
 
340
  impl InnerVoiceLesson {
341
- fn new(
342
- parent: LangLesson,
343
- voice: VoiceId,
344
- ) -> InnerVoiceLesson {
345
  let shared_voice_id: VoiceId = voice.clone();
346
  let (tx, rx) = tokio::sync::oneshot::channel::<Signal>();
347
  let mut translate_rx = parent.inner.translated_tx.subscribe();
@@ -361,7 +342,7 @@ impl InnerVoiceLesson {
361
  while let Some(Ok(bytes)) = audio_stream.next().await {
362
  let _ = &shared_voice_lesson.send(bytes.to_vec());
363
  }
364
- },
365
  Err(e) => {
366
  return Err(e);
367
  }
@@ -396,8 +377,9 @@ impl Drop for InnerVoiceLesson {
396
  }
397
  }
398
 
399
-
400
- fn to_stream(mut output: StartStreamTranscriptionOutput) -> impl Stream<Item=Result<String, StreamTranscriptionError>> {
 
401
  stream! {
402
  while let Some(event) = output
403
  .transcript_result_stream
@@ -434,16 +416,20 @@ enum SynthesizeError {
434
  Transmitting(aws_sdk_polly::error::BoxError),
435
  }
436
 
437
- async fn synthesize_speech(client: &aws_sdk_polly::Client,
438
- text: String,
439
- voice_id: VoiceId) -> Result<(Vec<Viseme>, ByteStream), SynthesizeError> {
440
- let audio_fut = client.synthesize_speech()
 
 
 
441
  .engine(Engine::Neural)
442
  .set_text(Some(text.clone()))
443
  .voice_id(voice_id.clone())
444
  .output_format(OutputFormat::Pcm)
445
  .send();
446
- let visemes_fut = client.synthesize_speech()
 
447
  .engine(Engine::Neural)
448
  .set_text(Some(text))
449
  .voice_id(voice_id)
@@ -453,8 +439,12 @@ async fn synthesize_speech(client: &aws_sdk_polly::Client,
453
  let (audio, visemes) = try_join(audio_fut, visemes_fut)
454
  .await
455
  .map_err(|e| SynthesizeError::Polly(e.into()))?;
456
- let visemes = visemes.audio_stream.collect().await
457
- .map_err(|e| SynthesizeError::Transmitting(e.into()))?.to_vec();
 
 
 
 
458
  let parsed: Vec<Viseme> = visemes
459
  .lines()
460
  .filter_map(|line| line.ok())
@@ -463,20 +453,22 @@ async fn synthesize_speech(client: &aws_sdk_polly::Client,
463
  Ok((parsed, audio.audio_stream))
464
  }
465
 
466
-
467
  #[derive(Debug)]
468
  enum StreamTranscriptionError {
469
  EstablishStreamError(Box<dyn Error + Send + Sync>),
470
  TranscriptResultStreamError(Box<dyn Error + Send + Sync>),
471
- Unknown
472
  }
473
 
474
-
475
  impl Display for StreamTranscriptionError {
476
  fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
477
  match self {
478
- StreamTranscriptionError::EstablishStreamError(e) => write!(f, "EstablishStreamError: {}", e),
479
- StreamTranscriptionError::TranscriptResultStreamError(e) => write!(f, "TranscriptResultStreamError: {}", e),
 
 
 
 
480
  StreamTranscriptionError::Unknown => write!(f, "Unknown"),
481
  }
482
  }
@@ -491,4 +483,3 @@ impl Error for StreamTranscriptionError {
491
  }
492
  }
493
  }
494
-
 
 
 
 
 
 
 
1
  use async_stream::stream;
2
  use aws_config::SdkConfig;
3
  use aws_sdk_polly::primitives::ByteStream;
4
  use aws_sdk_polly::types::{Engine, OutputFormat, SpeechMarkType, VoiceId};
5
  use aws_sdk_transcribestreaming::operation::start_stream_transcription::StartStreamTranscriptionOutput;
6
  use aws_sdk_transcribestreaming::primitives::Blob;
7
+ use aws_sdk_transcribestreaming::types::{
8
+ AudioEvent, AudioStream, LanguageCode, MediaEncoding, TranscriptResultStream,
9
+ };
10
  use futures_util::future::try_join;
11
+ use futures_util::{Stream, StreamExt, TryStreamExt};
12
  use serde::{Deserialize, Serialize};
13
+ use std::collections::BTreeMap;
14
+ use std::error::Error;
15
+ use std::fmt::{Display, Formatter};
16
+ use std::io::BufRead;
17
+ use std::sync::{Arc, Weak};
18
+ use tokio::sync::RwLock;
19
 
20
  use tokio::select;
21
 
 
24
  translate_client: aws_sdk_translate::Client,
25
  polly_client: aws_sdk_polly::Client,
26
  transcript_client: aws_sdk_transcribestreaming::Client,
27
+ lessons: Arc<RwLock<BTreeMap<u32, Lesson>>>,
28
  }
29
 
30
  impl LessonsManager {
 
36
  translate_client,
37
  polly_client,
38
  transcript_client,
39
+ lessons: Arc::new(RwLock::new(BTreeMap::new())),
40
  }
41
  }
42
 
43
+ pub(crate) async fn create_lesson(&self, id: u32, speaker_lang: LanguageCode) -> Lesson {
 
 
44
  let mut map = self.lessons.write().await;
45
  let lesson: Lesson = InnerLesson::new(self.clone(), speaker_lang).into();
46
  map.insert(id, lesson.clone());
 
55
 
56
  #[derive(Clone, Debug)]
57
  pub(crate) struct Lesson {
58
+ inner: Arc<InnerLesson>,
59
  }
60
 
61
  impl Lesson {
 
71
  if let Some(lang_lesson) = map.get(&lang).and_then(|weak| weak.upgrade()) {
72
  lang_lesson.into()
73
  } else {
74
+ let lang_lesson = LangLesson::new(self.clone(), lang.clone());
 
 
 
75
  map.insert(lang.clone(), Arc::downgrade(&lang_lesson.inner));
76
  lang_lesson
77
  }
 
90
  impl From<InnerLesson> for Lesson {
91
  fn from(inner: InnerLesson) -> Self {
92
  Lesson {
93
+ inner: Arc::new(inner),
94
  }
95
  }
96
  }
 
106
  }
107
 
108
  impl InnerLesson {
109
+ fn new(parent: LessonsManager, speaker_lang: LanguageCode) -> InnerLesson {
 
 
 
110
  let (speaker_transcript, _) = tokio::sync::broadcast::channel::<String>(128);
111
  let shared_speaker_transcript = speaker_transcript.clone();
112
  let (speaker_voice_channel, mut speaker_voice_rx) = tokio::sync::mpsc::channel(128);
 
123
  };
124
  let output = transcript_client
125
  .start_stream_transcription()
126
+ .language_code(shared_speak_lang) //LanguageCode::EnGb
127
  .media_sample_rate_hertz(16000)
128
  .media_encoding(MediaEncoding::Pcm)
129
  .audio_stream(input_stream.into())
 
169
  }
170
  }
171
 
 
172
  struct InnerLangLesson {
173
  parent: Lesson,
174
  translated_tx: tokio::sync::broadcast::Sender<String>,
 
186
 
187
  #[derive(Clone)]
188
  pub(crate) struct LangLesson {
189
+ inner: Arc<InnerLangLesson>,
190
  }
191
 
192
  impl LangLesson {
 
198
  impl From<InnerLangLesson> for LangLesson {
199
  fn from(inner: InnerLangLesson) -> Self {
200
  LangLesson {
201
+ inner: Arc::new(inner),
202
  }
203
  }
204
  }
205
 
206
  impl From<Arc<InnerLangLesson>> for LangLesson {
207
  fn from(inner: Arc<InnerLangLesson>) -> Self {
208
+ LangLesson { inner }
 
 
209
  }
210
  }
211
 
212
  impl LangLesson {
213
+ fn new(parent: Lesson, lang: String) -> Self {
 
 
 
214
  let shared_lang = lang.clone();
215
  let shared_speaker_lang = parent.inner.speaker_lang.clone();
216
  let (translated_tx, _) = tokio::sync::broadcast::channel::<String>(128);
 
233
  if let Some(translated) = res.translated_text {
234
  let _ = shared_translated_tx.send(translated);
235
  }
236
+ }
237
  Err(e) => {
238
  return Err(e);
239
  }
 
256
  translated_tx,
257
  voice_lessons: RwLock::new(BTreeMap::new()),
258
  drop_handler: Some(drop_handler),
259
+ }
260
+ .into()
261
  }
262
 
263
  pub(crate) async fn get_or_init(&mut self, voice: VoiceId) -> VoiceLesson {
 
273
  if let Some(voice_lesson) = map.get(&voice).and_then(|weak| weak.upgrade()) {
274
  voice_lesson.into()
275
  } else {
276
+ let voice_lesson = Arc::new(InnerVoiceLesson::new(self.clone(), voice.clone()));
 
 
 
277
  map.insert(voice, Arc::downgrade(&voice_lesson));
278
  voice_lesson.into()
279
  }
 
283
 
284
  #[derive(Clone)]
285
  pub(crate) struct VoiceLesson {
286
+ inner: Arc<InnerVoiceLesson>,
287
  }
288
 
289
  impl VoiceLesson {
 
299
  impl From<InnerVoiceLesson> for VoiceLesson {
300
  fn from(inner: InnerVoiceLesson) -> Self {
301
  VoiceLesson {
302
+ inner: Arc::new(inner),
303
  }
304
  }
305
  }
306
 
307
  impl From<Arc<InnerVoiceLesson>> for VoiceLesson {
308
  fn from(inner: Arc<InnerVoiceLesson>) -> Self {
309
+ VoiceLesson { inner }
 
 
310
  }
311
  }
312
 
 
322
  }
323
 
324
  impl InnerVoiceLesson {
325
+ fn new(parent: LangLesson, voice: VoiceId) -> InnerVoiceLesson {
 
 
 
326
  let shared_voice_id: VoiceId = voice.clone();
327
  let (tx, rx) = tokio::sync::oneshot::channel::<Signal>();
328
  let mut translate_rx = parent.inner.translated_tx.subscribe();
 
342
  while let Some(Ok(bytes)) = audio_stream.next().await {
343
  let _ = &shared_voice_lesson.send(bytes.to_vec());
344
  }
345
+ }
346
  Err(e) => {
347
  return Err(e);
348
  }
 
377
  }
378
  }
379
 
380
+ fn to_stream(
381
+ mut output: StartStreamTranscriptionOutput,
382
+ ) -> impl Stream<Item = Result<String, StreamTranscriptionError>> {
383
  stream! {
384
  while let Some(event) = output
385
  .transcript_result_stream
 
416
  Transmitting(aws_sdk_polly::error::BoxError),
417
  }
418
 
419
+ async fn synthesize_speech(
420
+ client: &aws_sdk_polly::Client,
421
+ text: String,
422
+ voice_id: VoiceId,
423
+ ) -> Result<(Vec<Viseme>, ByteStream), SynthesizeError> {
424
+ let audio_fut = client
425
+ .synthesize_speech()
426
  .engine(Engine::Neural)
427
  .set_text(Some(text.clone()))
428
  .voice_id(voice_id.clone())
429
  .output_format(OutputFormat::Pcm)
430
  .send();
431
+ let visemes_fut = client
432
+ .synthesize_speech()
433
  .engine(Engine::Neural)
434
  .set_text(Some(text))
435
  .voice_id(voice_id)
 
439
  let (audio, visemes) = try_join(audio_fut, visemes_fut)
440
  .await
441
  .map_err(|e| SynthesizeError::Polly(e.into()))?;
442
+ let visemes = visemes
443
+ .audio_stream
444
+ .collect()
445
+ .await
446
+ .map_err(|e| SynthesizeError::Transmitting(e.into()))?
447
+ .to_vec();
448
  let parsed: Vec<Viseme> = visemes
449
  .lines()
450
  .filter_map(|line| line.ok())
 
453
  Ok((parsed, audio.audio_stream))
454
  }
455
 
 
456
  #[derive(Debug)]
457
  enum StreamTranscriptionError {
458
  EstablishStreamError(Box<dyn Error + Send + Sync>),
459
  TranscriptResultStreamError(Box<dyn Error + Send + Sync>),
460
+ Unknown,
461
  }
462
 
 
463
  impl Display for StreamTranscriptionError {
464
  fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
465
  match self {
466
+ StreamTranscriptionError::EstablishStreamError(e) => {
467
+ write!(f, "EstablishStreamError: {}", e)
468
+ }
469
+ StreamTranscriptionError::TranscriptResultStreamError(e) => {
470
+ write!(f, "TranscriptResultStreamError: {}", e)
471
+ }
472
  StreamTranscriptionError::Unknown => write!(f, "Unknown"),
473
  }
474
  }
 
483
  }
484
  }
485
  }
 
src/main.rs CHANGED
@@ -5,30 +5,29 @@
5
 
6
  #![allow(clippy::result_large_err)]
7
 
8
- use std::default::Default;
9
  use aws_config::meta::region::RegionProviderChain;
10
  use aws_sdk_transcribestreaming::{config::Region, meta::PKG_VERSION};
11
  use clap::Parser;
 
12
 
13
- use poem::{EndpointExt, get, handler, IntoResponse, listener::TcpListener, Route, Server};
14
- use futures_util::{SinkExt};
15
  use poem::endpoint::{StaticFileEndpoint, StaticFilesEndpoint};
16
  use poem::web::websocket::{Message, WebSocket};
17
- use futures_util::stream::StreamExt;
18
  use poem::web::{Data, Query};
 
19
 
20
- use tokio::{select};
21
- use serde::{Deserialize, Serialize};
22
- use lesson::{LessonsManager};
23
  use crate::config::CONFIG;
24
  use crate::lesson::Viseme;
25
  use crate::whisper::WhisperHandler;
 
 
 
26
 
27
- mod lesson;
28
  mod config;
29
- mod whisper;
30
  mod group;
31
-
 
32
 
33
  #[derive(Debug, Parser)]
34
  struct Opt {
@@ -42,14 +41,11 @@ struct Context {
42
  lessons_manager: LessonsManager,
43
  }
44
 
45
-
46
  #[tokio::main]
47
  async fn main() -> Result<(), std::io::Error> {
48
  tracing_subscriber::fmt::init();
49
 
50
- let Opt {
51
- region,
52
- } = Opt::parse();
53
 
54
  let region_provider = RegionProviderChain::first_try(region.map(Region::new))
55
  .or_default_provider()
@@ -70,15 +66,21 @@ async fn main() -> Result<(), std::io::Error> {
70
 
71
  let app = Route::new()
72
  .nest(
73
- "/",
74
- StaticFilesEndpoint::new("./static")
75
- .show_files_listing()
76
- .index_file("index.html"),
77
  )
78
  .at("/ws/lesson-speaker", get(stream_speaker))
79
  .at("/ws/lesson-listener", get(stream_listener))
80
- .at("lesson-speaker", StaticFileEndpoint::new("./static/index.html"))
81
- .at("lesson-listener", StaticFileEndpoint::new("./static/index.html"))
 
 
 
 
 
 
82
  .data(ctx);
83
  let addr = format!("{}:{}", CONFIG.server.host, CONFIG.server.port);
84
  let listener = TcpListener::bind(addr);
@@ -87,7 +89,6 @@ async fn main() -> Result<(), std::io::Error> {
87
  server.run(app).await
88
  }
89
 
90
-
91
  #[derive(Deserialize, Debug)]
92
  pub struct LessonSpeakerQuery {
93
  id: u32,
@@ -96,14 +97,25 @@ pub struct LessonSpeakerQuery {
96
  }
97
 
98
  #[handler]
99
- async fn stream_speaker(ctx: Data<&Context>, query: Query<LessonSpeakerQuery>, ws: WebSocket) -> impl IntoResponse {
100
- let lesson = ctx.lessons_manager.create_lesson(query.id, query.lang.clone().parse().expect("Not supported lang")).await;
 
 
 
 
 
 
 
 
 
 
101
  let prompt = query.prompt.clone().unwrap_or_default();
102
 
103
  ws.on_upgrade(|mut socket| async move {
104
  let origin_tx = lesson.voice_channel();
105
  let mut transcribe_rx = lesson.transcript_channel();
106
- let whisper = WhisperHandler::new(CONFIG.whisper.clone(), prompt).expect("failed to create whisper");
 
107
  let mut whisper_transcribe_rx = whisper.subscribe();
108
  loop {
109
  select! {
@@ -149,7 +161,6 @@ async fn stream_speaker(ctx: Data<&Context>, query: Query<LessonSpeakerQuery>, w
149
  })
150
  }
151
 
152
-
153
  #[derive(Deserialize, Debug)]
154
  pub struct LessonListenerQuery {
155
  id: u32,
@@ -162,11 +173,15 @@ pub struct LessonListenerQuery {
162
  enum LiveLessonTextEvent {
163
  Transcription { text: String },
164
  Translation { text: String },
165
- LipSync{ visemes: Vec<Viseme> },
166
  }
167
 
168
  #[handler]
169
- async fn stream_listener(ctx: Data<&Context>, query: Query<LessonListenerQuery>, ws: WebSocket) -> impl IntoResponse {
 
 
 
 
170
  let lesson_opt = ctx.lessons_manager.get_lesson(query.id).await;
171
  tracing::debug!("listener param = {:?}", query);
172
 
@@ -174,13 +189,17 @@ async fn stream_listener(ctx: Data<&Context>, query: Query<LessonListenerQuery>,
174
  let voice_id = match query.voice.parse() {
175
  Ok(id) => id,
176
  Err(e) => {
177
- let _ = socket.send(Message::Text(format!("invalid voice id: {}", e))).await;
178
- return
 
 
179
  }
180
  };
181
  let Some(lesson) = lesson_opt else {
182
- let _ = socket.send(Message::Text("lesson not found".to_string())).await;
183
- return
 
 
184
  };
185
  let mut transcript_rx = lesson.transcript_channel();
186
  let mut lang_lesson = lesson.get_or_init(query.lang.clone()).await;
 
5
 
6
  #![allow(clippy::result_large_err)]
7
 
 
8
  use aws_config::meta::region::RegionProviderChain;
9
  use aws_sdk_transcribestreaming::{config::Region, meta::PKG_VERSION};
10
  use clap::Parser;
11
+ use std::default::Default;
12
 
13
+ use futures_util::stream::StreamExt;
14
+ use futures_util::SinkExt;
15
  use poem::endpoint::{StaticFileEndpoint, StaticFilesEndpoint};
16
  use poem::web::websocket::{Message, WebSocket};
 
17
  use poem::web::{Data, Query};
18
+ use poem::{get, handler, listener::TcpListener, EndpointExt, IntoResponse, Route, Server};
19
 
 
 
 
20
  use crate::config::CONFIG;
21
  use crate::lesson::Viseme;
22
  use crate::whisper::WhisperHandler;
23
+ use lesson::LessonsManager;
24
+ use serde::{Deserialize, Serialize};
25
+ use tokio::select;
26
 
 
27
  mod config;
 
28
  mod group;
29
+ mod lesson;
30
+ mod whisper;
31
 
32
  #[derive(Debug, Parser)]
33
  struct Opt {
 
41
  lessons_manager: LessonsManager,
42
  }
43
 
 
44
  #[tokio::main]
45
  async fn main() -> Result<(), std::io::Error> {
46
  tracing_subscriber::fmt::init();
47
 
48
+ let Opt { region } = Opt::parse();
 
 
49
 
50
  let region_provider = RegionProviderChain::first_try(region.map(Region::new))
51
  .or_default_provider()
 
66
 
67
  let app = Route::new()
68
  .nest(
69
+ "/",
70
+ StaticFilesEndpoint::new("./static")
71
+ .show_files_listing()
72
+ .index_file("index.html"),
73
  )
74
  .at("/ws/lesson-speaker", get(stream_speaker))
75
  .at("/ws/lesson-listener", get(stream_listener))
76
+ .at(
77
+ "lesson-speaker",
78
+ StaticFileEndpoint::new("./static/index.html"),
79
+ )
80
+ .at(
81
+ "lesson-listener",
82
+ StaticFileEndpoint::new("./static/index.html"),
83
+ )
84
  .data(ctx);
85
  let addr = format!("{}:{}", CONFIG.server.host, CONFIG.server.port);
86
  let listener = TcpListener::bind(addr);
 
89
  server.run(app).await
90
  }
91
 
 
92
  #[derive(Deserialize, Debug)]
93
  pub struct LessonSpeakerQuery {
94
  id: u32,
 
97
  }
98
 
99
  #[handler]
100
+ async fn stream_speaker(
101
+ ctx: Data<&Context>,
102
+ query: Query<LessonSpeakerQuery>,
103
+ ws: WebSocket,
104
+ ) -> impl IntoResponse {
105
+ let lesson = ctx
106
+ .lessons_manager
107
+ .create_lesson(
108
+ query.id,
109
+ query.lang.clone().parse().expect("Not supported lang"),
110
+ )
111
+ .await;
112
  let prompt = query.prompt.clone().unwrap_or_default();
113
 
114
  ws.on_upgrade(|mut socket| async move {
115
  let origin_tx = lesson.voice_channel();
116
  let mut transcribe_rx = lesson.transcript_channel();
117
+ let whisper =
118
+ WhisperHandler::new(CONFIG.whisper.clone(), prompt).expect("failed to create whisper");
119
  let mut whisper_transcribe_rx = whisper.subscribe();
120
  loop {
121
  select! {
 
161
  })
162
  }
163
 
 
164
  #[derive(Deserialize, Debug)]
165
  pub struct LessonListenerQuery {
166
  id: u32,
 
173
  enum LiveLessonTextEvent {
174
  Transcription { text: String },
175
  Translation { text: String },
176
+ LipSync { visemes: Vec<Viseme> },
177
  }
178
 
179
  #[handler]
180
+ async fn stream_listener(
181
+ ctx: Data<&Context>,
182
+ query: Query<LessonListenerQuery>,
183
+ ws: WebSocket,
184
+ ) -> impl IntoResponse {
185
  let lesson_opt = ctx.lessons_manager.get_lesson(query.id).await;
186
  tracing::debug!("listener param = {:?}", query);
187
 
 
189
  let voice_id = match query.voice.parse() {
190
  Ok(id) => id,
191
  Err(e) => {
192
+ let _ = socket
193
+ .send(Message::Text(format!("invalid voice id: {}", e)))
194
+ .await;
195
+ return;
196
  }
197
  };
198
  let Some(lesson) = lesson_opt else {
199
+ let _ = socket
200
+ .send(Message::Text("lesson not found".to_string()))
201
+ .await;
202
+ return;
203
  };
204
  let mut transcript_rx = lesson.transcript_channel();
205
  let mut lang_lesson = lesson.get_or_init(query.lang.clone()).await;
src/whisper.rs CHANGED
@@ -1,20 +1,18 @@
 
 
 
1
  use std::collections::VecDeque;
2
  use std::ffi::c_int;
3
  use std::fmt::{Debug, Display, Formatter};
4
  use std::thread::sleep;
5
  use std::time::Duration;
6
- use lazy_static::lazy_static;
7
  use tokio::sync::{broadcast, mpsc, oneshot};
8
- use whisper_rs::{convert_integer_to_float_audio, WhisperState, WhisperContext, WhisperToken};
9
  use whisper_rs_sys::WHISPER_SAMPLE_RATE;
10
- use crate::config::{CONFIG, WhisperConfig};
11
- use crate::group::GroupedWithin;
12
 
13
  lazy_static! {
14
- static ref WHISPER_CONTEXT: WhisperContext = {
15
- WhisperContext::new(&*CONFIG.whisper.model)
16
- .expect("failed to create WhisperContext")
17
- };
18
  }
19
 
20
  #[derive(Debug)]
@@ -84,7 +82,8 @@ impl WhisperHandler {
84
  let (pcm_tx, pcm_rx) = mpsc::channel::<Vec<u8>>(128);
85
  let (transcription_tx, _) = broadcast::channel::<Vec<Segment>>(128);
86
  let shared_transcription_tx = transcription_tx.clone();
87
- let state = WHISPER_CONTEXT.create_state()
 
88
  .map_err(|e| Error::whisper_error("failed to create WhisperState", e))?;
89
  let preset_prompt_tokens = WHISPER_CONTEXT
90
  .tokenize(prompt.as_str(), CONFIG.whisper.max_prompt_tokens)
@@ -95,46 +94,46 @@ impl WhisperHandler {
95
  detector.n_samples_step * 2,
96
  Duration::from_millis(config.step_ms as u64),
97
  pcm_rx,
98
- u16::MAX as usize
99
  );
100
  while let Err(oneshot::error::TryRecvError::Empty) = stop_signal.try_recv() {
101
  let new_pcm_f32 = match grouped.next() {
102
  Err(mpsc::error::TryRecvError::Disconnected) => break,
103
  Err(mpsc::error::TryRecvError::Empty) => {
104
  sleep(Duration::from_millis(10));
105
- continue
106
- }
107
- Ok(data) => {
108
- pcm_i16_to_f32(&data)
109
  }
 
110
  };
111
 
112
  detector.feed(new_pcm_f32);
113
  let segments = match detector.inference() {
114
  Ok(result) => {
115
  if result.is_empty() {
116
- continue
117
  }
118
  result
119
  }
120
  Err(err) => {
121
  tracing::warn!("failed to inference: {}", err);
122
- continue
123
  }
124
  };
125
 
126
  if tracing::enabled!(tracing::Level::TRACE) {
127
  for segment in segments.iter() {
128
- tracing::trace!("[{}-{}]s SEGMENT: {}",
 
129
  segment.start_timestamp as f32 / 1000.0,
130
  segment.end_timestamp as f32 / 1000.0,
131
- segment.text);
 
132
  }
133
  }
134
 
135
  if let Err(e) = shared_transcription_tx.send(segments) {
136
  tracing::error!("failed to send transcription: {}", e);
137
- break
138
  };
139
  }
140
  });
@@ -168,10 +167,11 @@ struct Detector {
168
  }
169
 
170
  impl Detector {
171
- fn new(state: WhisperState<'static>,
172
- config: &'static WhisperConfig,
173
- preset_prompt_tokens: Vec<WhisperToken>) -> Self {
174
-
 
175
  Detector {
176
  state,
177
  config,
@@ -182,51 +182,71 @@ impl Detector {
182
  prompt_tokens: Default::default(),
183
  pcm_f32: VecDeque::from(vec![0f32; 30 * WHISPER_SAMPLE_RATE as usize]),
184
  offset: 0,
185
- stable_offset: 0
186
  }
187
  }
188
 
189
  fn feed(&mut self, new_pcm_f32: Vec<f32>) {
190
  self.pcm_f32.extend(new_pcm_f32);
191
  if self.pcm_f32.len() < self.n_samples_len {
192
- return
193
  }
194
- let len_to_drain = self.pcm_f32.drain(0..(self.pcm_f32.len() - self.n_samples_len)).len();
 
 
 
195
  self.offset += len_to_drain;
196
  }
197
 
198
  fn inference(&mut self) -> Result<Vec<Segment>, Error> {
199
- let prompt_tokens = [self.preset_prompt_tokens.as_slice(), self.prompt_tokens.as_slice()].concat();
 
 
 
 
200
  let params = self.config.params.to_full_params(prompt_tokens.as_slice());
201
  let start = std::time::Instant::now();
202
- let _ = self.state.full(params, self.pcm_f32.make_contiguous())
 
 
203
  .map_err(|e| Error::whisper_error("failed to initialize WhisperState", e))?;
204
  let end = std::time::Instant::now();
205
  if end - start > Duration::from_millis(self.config.step_ms as u64) {
206
- tracing::warn!("full([{}]) took {} ms too slow", self.pcm_f32.len(), (end - start).as_millis());
 
 
 
 
207
  }
208
 
209
  let timestamp_offset: i64 = (self.offset * 1000 / WHISPER_SAMPLE_RATE as usize) as i64;
210
  let stable_offset: i64 = (self.stable_offset * 1000 / WHISPER_SAMPLE_RATE as usize) as i64;
211
- let num_segments = self.state
 
212
  .full_n_segments()
213
  .map_err(|e| Error::whisper_error("failed to get number of segments", e))?;
214
  let mut segments: Vec<Segment> = Vec::with_capacity(num_segments as usize);
215
  for i in 0..num_segments {
216
- let end_timestamp: i64 = timestamp_offset + 10 * self.state
217
- .full_get_segment_t1(i)
218
- .map_err(|e| Error::whisper_error("failed to get end timestamp", e))?;
 
 
219
  if end_timestamp <= stable_offset {
220
- continue
221
  }
222
 
223
- let start_timestamp: i64 = timestamp_offset + 10 * self.state
224
- .full_get_segment_t0(i)
225
- .map_err(|e| Error::whisper_error("failed to get start timestamp", e))?;
226
- let segment = self.state
 
 
 
227
  .full_get_segment_text(i)
228
  .map_err(|e| Error::whisper_error("failed to get segment", e))?;
229
- let num_tokens = self.state
 
230
  .full_n_tokens(i)
231
  .map_err(|e| Error::whisper_error("failed to get segment tokens", e))?;
232
  let mut segment_tokens = Vec::with_capacity(num_tokens as usize);
@@ -234,22 +254,28 @@ impl Detector {
234
  segment_tokens.push(
235
  self.state
236
  .full_get_token_id(i, j)
237
- .map_err(|e| Error::whisper_error("failed to get token", e))?
238
  );
239
  }
240
 
241
- segments.push(Segment { start_timestamp, end_timestamp, text: segment.trim().to_string(), tokens: segment_tokens });
 
 
 
 
 
242
  }
243
 
244
  let Some((_last, init)) = segments.split_last() else {
245
- return Ok(Vec::default())
246
  };
247
 
248
  let Some((last_2_seg, _)) = init.split_last() else {
249
- return Ok(Vec::default())
250
  };
251
 
252
- let offset = (last_2_seg.end_timestamp - timestamp_offset) as usize / 1000 * WHISPER_SAMPLE_RATE as usize;
 
253
  self.stable_offset = offset;
254
  self.drop_stable_by_segments(init);
255
  Ok(init.into())
@@ -257,9 +283,10 @@ impl Detector {
257
 
258
  fn drop_stable_by_segments(&mut self, stable_segments: &[Segment]) {
259
  let Some(last) = stable_segments.last() else {
260
- return
261
  };
262
- let drop_offset: usize = (last.end_timestamp as usize / 1000 * WHISPER_SAMPLE_RATE as usize - self.offset) as usize;
 
263
  let len_to_drain = self.pcm_f32.drain(0..drop_offset).len();
264
  self.offset += len_to_drain;
265
 
@@ -267,7 +294,10 @@ impl Detector {
267
  self.prompt_tokens.extend(&segment.tokens);
268
  }
269
  if self.prompt_tokens.len() > self.config.max_prompt_tokens {
270
- let _ = self.prompt_tokens.drain(0..(self.prompt_tokens.len() - self.config.max_prompt_tokens)).len();
 
 
 
271
  }
272
  }
273
  }
 
1
+ use crate::config::{WhisperConfig, CONFIG};
2
+ use crate::group::GroupedWithin;
3
+ use lazy_static::lazy_static;
4
  use std::collections::VecDeque;
5
  use std::ffi::c_int;
6
  use std::fmt::{Debug, Display, Formatter};
7
  use std::thread::sleep;
8
  use std::time::Duration;
 
9
  use tokio::sync::{broadcast, mpsc, oneshot};
10
+ use whisper_rs::{convert_integer_to_float_audio, WhisperContext, WhisperState, WhisperToken};
11
  use whisper_rs_sys::WHISPER_SAMPLE_RATE;
 
 
12
 
13
  lazy_static! {
14
+ static ref WHISPER_CONTEXT: WhisperContext =
15
+ { WhisperContext::new(&*CONFIG.whisper.model).expect("failed to create WhisperContext") };
 
 
16
  }
17
 
18
  #[derive(Debug)]
 
82
  let (pcm_tx, pcm_rx) = mpsc::channel::<Vec<u8>>(128);
83
  let (transcription_tx, _) = broadcast::channel::<Vec<Segment>>(128);
84
  let shared_transcription_tx = transcription_tx.clone();
85
+ let state = WHISPER_CONTEXT
86
+ .create_state()
87
  .map_err(|e| Error::whisper_error("failed to create WhisperState", e))?;
88
  let preset_prompt_tokens = WHISPER_CONTEXT
89
  .tokenize(prompt.as_str(), CONFIG.whisper.max_prompt_tokens)
 
94
  detector.n_samples_step * 2,
95
  Duration::from_millis(config.step_ms as u64),
96
  pcm_rx,
97
+ u16::MAX as usize,
98
  );
99
  while let Err(oneshot::error::TryRecvError::Empty) = stop_signal.try_recv() {
100
  let new_pcm_f32 = match grouped.next() {
101
  Err(mpsc::error::TryRecvError::Disconnected) => break,
102
  Err(mpsc::error::TryRecvError::Empty) => {
103
  sleep(Duration::from_millis(10));
104
+ continue;
 
 
 
105
  }
106
+ Ok(data) => pcm_i16_to_f32(&data),
107
  };
108
 
109
  detector.feed(new_pcm_f32);
110
  let segments = match detector.inference() {
111
  Ok(result) => {
112
  if result.is_empty() {
113
+ continue;
114
  }
115
  result
116
  }
117
  Err(err) => {
118
  tracing::warn!("failed to inference: {}", err);
119
+ continue;
120
  }
121
  };
122
 
123
  if tracing::enabled!(tracing::Level::TRACE) {
124
  for segment in segments.iter() {
125
+ tracing::trace!(
126
+ "[{}-{}]s SEGMENT: {}",
127
  segment.start_timestamp as f32 / 1000.0,
128
  segment.end_timestamp as f32 / 1000.0,
129
+ segment.text
130
+ );
131
  }
132
  }
133
 
134
  if let Err(e) = shared_transcription_tx.send(segments) {
135
  tracing::error!("failed to send transcription: {}", e);
136
+ break;
137
  };
138
  }
139
  });
 
167
  }
168
 
169
  impl Detector {
170
+ fn new(
171
+ state: WhisperState<'static>,
172
+ config: &'static WhisperConfig,
173
+ preset_prompt_tokens: Vec<WhisperToken>,
174
+ ) -> Self {
175
  Detector {
176
  state,
177
  config,
 
182
  prompt_tokens: Default::default(),
183
  pcm_f32: VecDeque::from(vec![0f32; 30 * WHISPER_SAMPLE_RATE as usize]),
184
  offset: 0,
185
+ stable_offset: 0,
186
  }
187
  }
188
 
189
  fn feed(&mut self, new_pcm_f32: Vec<f32>) {
190
  self.pcm_f32.extend(new_pcm_f32);
191
  if self.pcm_f32.len() < self.n_samples_len {
192
+ return;
193
  }
194
+ let len_to_drain = self
195
+ .pcm_f32
196
+ .drain(0..(self.pcm_f32.len() - self.n_samples_len))
197
+ .len();
198
  self.offset += len_to_drain;
199
  }
200
 
201
  fn inference(&mut self) -> Result<Vec<Segment>, Error> {
202
+ let prompt_tokens = [
203
+ self.preset_prompt_tokens.as_slice(),
204
+ self.prompt_tokens.as_slice(),
205
+ ]
206
+ .concat();
207
  let params = self.config.params.to_full_params(prompt_tokens.as_slice());
208
  let start = std::time::Instant::now();
209
+ let _ = self
210
+ .state
211
+ .full(params, self.pcm_f32.make_contiguous())
212
  .map_err(|e| Error::whisper_error("failed to initialize WhisperState", e))?;
213
  let end = std::time::Instant::now();
214
  if end - start > Duration::from_millis(self.config.step_ms as u64) {
215
+ tracing::warn!(
216
+ "full([{}]) took {} ms too slow",
217
+ self.pcm_f32.len(),
218
+ (end - start).as_millis()
219
+ );
220
  }
221
 
222
  let timestamp_offset: i64 = (self.offset * 1000 / WHISPER_SAMPLE_RATE as usize) as i64;
223
  let stable_offset: i64 = (self.stable_offset * 1000 / WHISPER_SAMPLE_RATE as usize) as i64;
224
+ let num_segments = self
225
+ .state
226
  .full_n_segments()
227
  .map_err(|e| Error::whisper_error("failed to get number of segments", e))?;
228
  let mut segments: Vec<Segment> = Vec::with_capacity(num_segments as usize);
229
  for i in 0..num_segments {
230
+ let end_timestamp: i64 = timestamp_offset
231
+ + 10 * self
232
+ .state
233
+ .full_get_segment_t1(i)
234
+ .map_err(|e| Error::whisper_error("failed to get end timestamp", e))?;
235
  if end_timestamp <= stable_offset {
236
+ continue;
237
  }
238
 
239
+ let start_timestamp: i64 = timestamp_offset
240
+ + 10 * self
241
+ .state
242
+ .full_get_segment_t0(i)
243
+ .map_err(|e| Error::whisper_error("failed to get start timestamp", e))?;
244
+ let segment = self
245
+ .state
246
  .full_get_segment_text(i)
247
  .map_err(|e| Error::whisper_error("failed to get segment", e))?;
248
+ let num_tokens = self
249
+ .state
250
  .full_n_tokens(i)
251
  .map_err(|e| Error::whisper_error("failed to get segment tokens", e))?;
252
  let mut segment_tokens = Vec::with_capacity(num_tokens as usize);
 
254
  segment_tokens.push(
255
  self.state
256
  .full_get_token_id(i, j)
257
+ .map_err(|e| Error::whisper_error("failed to get token", e))?,
258
  );
259
  }
260
 
261
+ segments.push(Segment {
262
+ start_timestamp,
263
+ end_timestamp,
264
+ text: segment.trim().to_string(),
265
+ tokens: segment_tokens,
266
+ });
267
  }
268
 
269
  let Some((_last, init)) = segments.split_last() else {
270
+ return Ok(Vec::default());
271
  };
272
 
273
  let Some((last_2_seg, _)) = init.split_last() else {
274
+ return Ok(Vec::default());
275
  };
276
 
277
+ let offset = (last_2_seg.end_timestamp - timestamp_offset) as usize / 1000
278
+ * WHISPER_SAMPLE_RATE as usize;
279
  self.stable_offset = offset;
280
  self.drop_stable_by_segments(init);
281
  Ok(init.into())
 
283
 
284
  fn drop_stable_by_segments(&mut self, stable_segments: &[Segment]) {
285
  let Some(last) = stable_segments.last() else {
286
+ return;
287
  };
288
+ let drop_offset: usize = (last.end_timestamp as usize / 1000 * WHISPER_SAMPLE_RATE as usize
289
+ - self.offset) as usize;
290
  let len_to_drain = self.pcm_f32.drain(0..drop_offset).len();
291
  self.offset += len_to_drain;
292
 
 
294
  self.prompt_tokens.extend(&segment.tokens);
295
  }
296
  if self.prompt_tokens.len() > self.config.max_prompt_tokens {
297
+ let _ = self
298
+ .prompt_tokens
299
+ .drain(0..(self.prompt_tokens.len() - self.config.max_prompt_tokens))
300
+ .len();
301
  }
302
  }
303
  }