├── .gitignore ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── README.md ├── samples ├── 3kliks-cut.mp3 └── jfk.wav └── src ├── lib.rs ├── tests.rs ├── transcode.rs └── transcript.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 0.2.0 4 | 5 | * Update libraries (whisper-rs 0.8.0 -> 0.11.1) 6 | * -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "adler" 7 | version = "1.0.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 10 | 11 | [[package]] 12 | name = "aho-corasick" 13 | version = "1.1.3" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 16 | dependencies = [ 17 | "memchr", 18 | ] 19 | 20 | [[package]] 21 | name = "alac" 22 | version = "0.5.0" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "498a34d3cad5f3b23cc217ab489424ebcfffed186e30ad5ac02624e50df2c2b8" 25 | dependencies = [ 26 | "mp4parse", 27 | ] 28 | 29 | [[package]] 30 | name = "alsa" 31 | version = "0.9.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "37fe60779335388a88c01ac6c3be40304d1e349de3ada3b15f7808bb90fa9dce" 34 | dependencies = [ 35 | "alsa-sys", 36 | "bitflags 2.5.0", 37 | "libc", 38 | ] 39 | 40 | [[package]] 41 | name = "alsa-sys" 42 | version = "0.3.1" 43 | source = "registry+https://github.com/rust-lang/crates.io-index" 44 | checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" 45 | dependencies = [ 46 | "libc", 47 | "pkg-config", 48 | ] 49 | 50 | [[package]] 51 | name = "arrayvec" 52 | version = "0.7.4" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" 55 | 56 | [[package]] 57 | name = "audrey" 58 | version = "0.3.0" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | checksum = "58b92a84e89497e3cd25d3672cd5d1c288abaac02c18ff21283f17d118b889b8" 61 | dependencies = [ 62 | "alac", 63 | "caf", 64 | "claxon", 65 | "dasp_frame", 66 | "dasp_sample", 67 | "hound", 68 | "lewton 0.9.4", 69 | ] 70 | 71 | [[package]] 72 | name = "autocfg" 73 | version = "1.3.0" 74 | source = "registry+https://github.com/rust-lang/crates.io-index" 75 | checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" 76 | 77 | [[package]] 78 | name = "base64" 79 | version = "0.22.1" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 82 | 83 | [[package]] 84 | name = "bindgen" 85 | version = "0.69.4" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" 88 | dependencies = [ 89 | "bitflags 2.5.0", 90 | "cexpr", 91 | "clang-sys", 92 | "itertools", 93 | "lazy_static", 94 | "lazycell", 95 | "log", 96 | "prettyplease", 97 | "proc-macro2", 98 | "quote", 99 | "regex", 100 | "rustc-hash", 101 | "shlex", 102 | "syn", 103 | "which", 104 | ] 105 | 106 | [[package]] 107 | name = "bitflags" 108 | version = "1.3.2" 109 | source = "registry+https://github.com/rust-lang/crates.io-index" 110 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 111 | 112 | [[package]] 113 | name = "bitflags" 114 | version = "2.5.0" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" 117 | 118 | [[package]] 119 | name = "bitreader" 120 | version = "0.3.8" 121 | source = "registry+https://github.com/rust-lang/crates.io-index" 122 | checksum = "bdd859c9d97f7c468252795b35aeccc412bdbb1e90ee6969c4fa6328272eaeff" 123 | dependencies = [ 124 | "cfg-if", 125 | ] 126 | 127 | [[package]] 128 | name = "bumpalo" 129 | version = "3.16.0" 130 | source = "registry+https://github.com/rust-lang/crates.io-index" 131 | checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" 132 | 133 | [[package]] 134 | name = "bytemuck" 135 | version = "1.16.1" 136 | source = "registry+https://github.com/rust-lang/crates.io-index" 137 | checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" 138 | 139 | [[package]] 140 | name = "byteorder" 141 | version = "1.5.0" 142 | source = "registry+https://github.com/rust-lang/crates.io-index" 143 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 144 | 145 | [[package]] 146 | name = "bytes" 147 | version = "1.6.0" 148 | source = "registry+https://github.com/rust-lang/crates.io-index" 149 | checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" 150 | 151 | [[package]] 152 | name = "caf" 153 | version = "0.1.0" 154 | source = "registry+https://github.com/rust-lang/crates.io-index" 155 | checksum = "8fb1715abe8ffd1caeca4e30b9d803ecb75698bef0e59d207d4b0f16757744e7" 156 | dependencies = [ 157 | "byteorder", 158 | ] 159 | 160 | [[package]] 161 | name = "cc" 162 | version = "1.0.100" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | checksum = "c891175c3fb232128f48de6590095e59198bbeb8620c310be349bfc3afd12c7b" 165 | dependencies = [ 166 | "jobserver", 167 | "libc", 168 | "once_cell", 169 | ] 170 | 171 | [[package]] 172 | name = "cesu8" 173 | version = "1.1.0" 174 | source = "registry+https://github.com/rust-lang/crates.io-index" 175 | checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" 176 | 177 | [[package]] 178 | name = "cexpr" 179 | version = "0.6.0" 180 | source = "registry+https://github.com/rust-lang/crates.io-index" 181 | checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" 182 | dependencies = [ 183 | "nom", 184 | ] 185 | 186 | [[package]] 187 | name = "cfg-if" 188 | version = "1.0.0" 189 | source = "registry+https://github.com/rust-lang/crates.io-index" 190 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 191 | 192 | [[package]] 193 | name = "clang-sys" 194 | version = "1.8.1" 195 | source = "registry+https://github.com/rust-lang/crates.io-index" 196 | checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" 197 | dependencies = [ 198 | "glob", 199 | "libc", 200 | "libloading", 201 | ] 202 | 203 | [[package]] 204 | name = "claxon" 205 | version = "0.4.3" 206 | source = "registry+https://github.com/rust-lang/crates.io-index" 207 | checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688" 208 | 209 | [[package]] 210 | name = "cmake" 211 | version = "0.1.50" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" 214 | dependencies = [ 215 | "cc", 216 | ] 217 | 218 | [[package]] 219 | name = "combine" 220 | version = "4.6.7" 221 | source = "registry+https://github.com/rust-lang/crates.io-index" 222 | checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" 223 | dependencies = [ 224 | "bytes", 225 | "memchr", 226 | ] 227 | 228 | [[package]] 229 | name = "core-foundation-sys" 230 | version = "0.8.6" 231 | source = "registry+https://github.com/rust-lang/crates.io-index" 232 | checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" 233 | 234 | [[package]] 235 | name = "coreaudio-rs" 236 | version = "0.11.3" 237 | source = "registry+https://github.com/rust-lang/crates.io-index" 238 | checksum = "321077172d79c662f64f5071a03120748d5bb652f5231570141be24cfcd2bace" 239 | dependencies = [ 240 | "bitflags 1.3.2", 241 | "core-foundation-sys", 242 | "coreaudio-sys", 243 | ] 244 | 245 | [[package]] 246 | name = "coreaudio-sys" 247 | version = "0.2.15" 248 | source = "registry+https://github.com/rust-lang/crates.io-index" 249 | checksum = "7f01585027057ff5f0a5bf276174ae4c1594a2c5bde93d5f46a016d76270f5a9" 250 | dependencies = [ 251 | "bindgen", 252 | ] 253 | 254 | [[package]] 255 | name = "cpal" 256 | version = "0.15.3" 257 | source = "registry+https://github.com/rust-lang/crates.io-index" 258 | checksum = "873dab07c8f743075e57f524c583985fbaf745602acbe916a01539364369a779" 259 | dependencies = [ 260 | "alsa", 261 | "core-foundation-sys", 262 | "coreaudio-rs", 263 | "dasp_sample", 264 | "jni", 265 | "js-sys", 266 | "libc", 267 | "mach2", 268 | "ndk", 269 | "ndk-context", 270 | "oboe", 271 | "wasm-bindgen", 272 | "wasm-bindgen-futures", 273 | "web-sys", 274 | "windows", 275 | ] 276 | 277 | [[package]] 278 | name = "crc32fast" 279 | version = "1.4.2" 280 | source = "registry+https://github.com/rust-lang/crates.io-index" 281 | checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" 282 | dependencies = [ 283 | "cfg-if", 284 | ] 285 | 286 | [[package]] 287 | name = "dasp_frame" 288 | version = "0.11.0" 289 | source = "registry+https://github.com/rust-lang/crates.io-index" 290 | checksum = "b2a3937f5fe2135702897535c8d4a5553f8b116f76c1529088797f2eee7c5cd6" 291 | dependencies = [ 292 | "dasp_sample", 293 | ] 294 | 295 | [[package]] 296 | name = "dasp_sample" 297 | version = "0.11.0" 298 | source = "registry+https://github.com/rust-lang/crates.io-index" 299 | checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" 300 | 301 | [[package]] 302 | name = "either" 303 | version = "1.12.0" 304 | source = "registry+https://github.com/rust-lang/crates.io-index" 305 | checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" 306 | 307 | [[package]] 308 | name = "encoding_rs" 309 | version = "0.8.34" 310 | source = "registry+https://github.com/rust-lang/crates.io-index" 311 | checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" 312 | dependencies = [ 313 | "cfg-if", 314 | ] 315 | 316 | [[package]] 317 | name = "equivalent" 318 | version = "1.0.1" 319 | source = "registry+https://github.com/rust-lang/crates.io-index" 320 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 321 | 322 | [[package]] 323 | name = "errno" 324 | version = "0.3.9" 325 | source = "registry+https://github.com/rust-lang/crates.io-index" 326 | checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" 327 | dependencies = [ 328 | "libc", 329 | "windows-sys 0.52.0", 330 | ] 331 | 332 | [[package]] 333 | name = "extended" 334 | version = "0.1.0" 335 | source = "registry+https://github.com/rust-lang/crates.io-index" 336 | checksum = "af9673d8203fcb076b19dfd17e38b3d4ae9f44959416ea532ce72415a6020365" 337 | 338 | [[package]] 339 | name = "flate2" 340 | version = "1.0.30" 341 | source = "registry+https://github.com/rust-lang/crates.io-index" 342 | checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" 343 | dependencies = [ 344 | "crc32fast", 345 | "miniz_oxide", 346 | ] 347 | 348 | [[package]] 349 | name = "form_urlencoded" 350 | version = "1.2.1" 351 | source = "registry+https://github.com/rust-lang/crates.io-index" 352 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 353 | dependencies = [ 354 | "percent-encoding", 355 | ] 356 | 357 | [[package]] 358 | name = "fs_extra" 359 | version = "1.3.0" 360 | source = "registry+https://github.com/rust-lang/crates.io-index" 361 | checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" 362 | 363 | [[package]] 364 | name = "getrandom" 365 | version = "0.2.15" 366 | source = "registry+https://github.com/rust-lang/crates.io-index" 367 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 368 | dependencies = [ 369 | "cfg-if", 370 | "libc", 371 | "wasi", 372 | ] 373 | 374 | [[package]] 375 | name = "glob" 376 | version = "0.3.1" 377 | source = "registry+https://github.com/rust-lang/crates.io-index" 378 | checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" 379 | 380 | [[package]] 381 | name = "hashbrown" 382 | version = "0.14.5" 383 | source = "registry+https://github.com/rust-lang/crates.io-index" 384 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 385 | 386 | [[package]] 387 | name = "heck" 388 | version = "0.5.0" 389 | source = "registry+https://github.com/rust-lang/crates.io-index" 390 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 391 | 392 | [[package]] 393 | name = "hermit-abi" 394 | version = "0.3.9" 395 | source = "registry+https://github.com/rust-lang/crates.io-index" 396 | checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" 397 | 398 | [[package]] 399 | name = "home" 400 | version = "0.5.9" 401 | source = "registry+https://github.com/rust-lang/crates.io-index" 402 | checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" 403 | dependencies = [ 404 | "windows-sys 0.52.0", 405 | ] 406 | 407 | [[package]] 408 | name = "hound" 409 | version = "3.5.1" 410 | source = "registry+https://github.com/rust-lang/crates.io-index" 411 | checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f" 412 | 413 | [[package]] 414 | name = "idna" 415 | version = "0.5.0" 416 | source = "registry+https://github.com/rust-lang/crates.io-index" 417 | checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" 418 | dependencies = [ 419 | "unicode-bidi", 420 | "unicode-normalization", 421 | ] 422 | 423 | [[package]] 424 | name = "indexmap" 425 | version = "2.2.6" 426 | source = "registry+https://github.com/rust-lang/crates.io-index" 427 | checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" 428 | dependencies = [ 429 | "equivalent", 430 | "hashbrown", 431 | ] 432 | 433 | [[package]] 434 | name = "itertools" 435 | version = "0.12.1" 436 | source = "registry+https://github.com/rust-lang/crates.io-index" 437 | checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" 438 | dependencies = [ 439 | "either", 440 | ] 441 | 442 | [[package]] 443 | name = "itoa" 444 | version = "1.0.11" 445 | source = "registry+https://github.com/rust-lang/crates.io-index" 446 | checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" 447 | 448 | [[package]] 449 | name = "jni" 450 | version = "0.21.1" 451 | source = "registry+https://github.com/rust-lang/crates.io-index" 452 | checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" 453 | dependencies = [ 454 | "cesu8", 455 | "cfg-if", 456 | "combine", 457 | "jni-sys", 458 | "log", 459 | "thiserror", 460 | "walkdir", 461 | "windows-sys 0.45.0", 462 | ] 463 | 464 | [[package]] 465 | name = "jni-sys" 466 | version = "0.3.0" 467 | source = "registry+https://github.com/rust-lang/crates.io-index" 468 | checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" 469 | 470 | [[package]] 471 | name = "jobserver" 472 | version = "0.1.31" 473 | source = "registry+https://github.com/rust-lang/crates.io-index" 474 | checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" 475 | dependencies = [ 476 | "libc", 477 | ] 478 | 479 | [[package]] 480 | name = "js-sys" 481 | version = "0.3.69" 482 | source = "registry+https://github.com/rust-lang/crates.io-index" 483 | checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" 484 | dependencies = [ 485 | "wasm-bindgen", 486 | ] 487 | 488 | [[package]] 489 | name = "lazy_static" 490 | version = "1.5.0" 491 | source = "registry+https://github.com/rust-lang/crates.io-index" 492 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 493 | 494 | [[package]] 495 | name = "lazycell" 496 | version = "1.3.0" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" 499 | 500 | [[package]] 501 | name = "lewton" 502 | version = "0.9.4" 503 | source = "registry+https://github.com/rust-lang/crates.io-index" 504 | checksum = "8d542c1a317036c45c2aa1cf10cc9d403ca91eb2d333ef1a4917e5cb10628bd0" 505 | dependencies = [ 506 | "byteorder", 507 | "ogg 0.7.1", 508 | "smallvec", 509 | ] 510 | 511 | [[package]] 512 | name = "lewton" 513 | version = "0.10.2" 514 | source = "registry+https://github.com/rust-lang/crates.io-index" 515 | checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030" 516 | dependencies = [ 517 | "byteorder", 518 | "ogg 0.8.0", 519 | "tinyvec", 520 | ] 521 | 522 | [[package]] 523 | name = "libc" 524 | version = "0.2.155" 525 | source = "registry+https://github.com/rust-lang/crates.io-index" 526 | checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" 527 | 528 | [[package]] 529 | name = "libloading" 530 | version = "0.8.4" 531 | source = "registry+https://github.com/rust-lang/crates.io-index" 532 | checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" 533 | dependencies = [ 534 | "cfg-if", 535 | "windows-targets 0.52.5", 536 | ] 537 | 538 | [[package]] 539 | name = "linux-raw-sys" 540 | version = "0.4.14" 541 | source = "registry+https://github.com/rust-lang/crates.io-index" 542 | checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" 543 | 544 | [[package]] 545 | name = "log" 546 | version = "0.4.21" 547 | source = "registry+https://github.com/rust-lang/crates.io-index" 548 | checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" 549 | 550 | [[package]] 551 | name = "mach2" 552 | version = "0.4.2" 553 | source = "registry+https://github.com/rust-lang/crates.io-index" 554 | checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" 555 | dependencies = [ 556 | "libc", 557 | ] 558 | 559 | [[package]] 560 | name = "maybe-uninit" 561 | version = "2.0.0" 562 | source = "registry+https://github.com/rust-lang/crates.io-index" 563 | checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" 564 | 565 | [[package]] 566 | name = "memchr" 567 | version = "2.7.4" 568 | source = "registry+https://github.com/rust-lang/crates.io-index" 569 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 570 | 571 | [[package]] 572 | name = "minimal-lexical" 573 | version = "0.2.1" 574 | source = "registry+https://github.com/rust-lang/crates.io-index" 575 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 576 | 577 | [[package]] 578 | name = "minimp3-sys" 579 | version = "0.3.2" 580 | source = "registry+https://github.com/rust-lang/crates.io-index" 581 | checksum = "e21c73734c69dc95696c9ed8926a2b393171d98b3f5f5935686a26a487ab9b90" 582 | dependencies = [ 583 | "cc", 584 | ] 585 | 586 | [[package]] 587 | name = "minimp3_fixed" 588 | version = "0.5.4" 589 | source = "registry+https://github.com/rust-lang/crates.io-index" 590 | checksum = "42b0f14e7e75da97ae396c2656b10262a3d4afa2ec98f35795630eff0c8b951b" 591 | dependencies = [ 592 | "minimp3-sys", 593 | "slice-ring-buffer", 594 | "thiserror", 595 | ] 596 | 597 | [[package]] 598 | name = "miniz_oxide" 599 | version = "0.7.4" 600 | source = "registry+https://github.com/rust-lang/crates.io-index" 601 | checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" 602 | dependencies = [ 603 | "adler", 604 | ] 605 | 606 | [[package]] 607 | name = "mp4parse" 608 | version = "0.10.1" 609 | source = "registry+https://github.com/rust-lang/crates.io-index" 610 | checksum = "7316728464443fe5793a805dde3257864e9690cf46374daff3ce93de1df2f254" 611 | dependencies = [ 612 | "bitreader", 613 | "byteorder", 614 | "log", 615 | "num-traits", 616 | ] 617 | 618 | [[package]] 619 | name = "mutter" 620 | version = "0.2.0" 621 | dependencies = [ 622 | "audrey", 623 | "glob", 624 | "log", 625 | "num", 626 | "num_cpus", 627 | "rodio", 628 | "serde", 629 | "serde_json", 630 | "strum", 631 | "ureq", 632 | "whisper-rs", 633 | ] 634 | 635 | [[package]] 636 | name = "ndk" 637 | version = "0.8.0" 638 | source = "registry+https://github.com/rust-lang/crates.io-index" 639 | checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" 640 | dependencies = [ 641 | "bitflags 2.5.0", 642 | "jni-sys", 643 | "log", 644 | "ndk-sys", 645 | "num_enum", 646 | "thiserror", 647 | ] 648 | 649 | [[package]] 650 | name = "ndk-context" 651 | version = "0.1.1" 652 | source = "registry+https://github.com/rust-lang/crates.io-index" 653 | checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" 654 | 655 | [[package]] 656 | name = "ndk-sys" 657 | version = "0.5.0+25.2.9519653" 658 | source = "registry+https://github.com/rust-lang/crates.io-index" 659 | checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" 660 | dependencies = [ 661 | "jni-sys", 662 | ] 663 | 664 | [[package]] 665 | name = "nom" 666 | version = "7.1.3" 667 | source = "registry+https://github.com/rust-lang/crates.io-index" 668 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 669 | dependencies = [ 670 | "memchr", 671 | "minimal-lexical", 672 | ] 673 | 674 | [[package]] 675 | name = "num" 676 | version = "0.4.3" 677 | source = "registry+https://github.com/rust-lang/crates.io-index" 678 | checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" 679 | dependencies = [ 680 | "num-bigint", 681 | "num-complex", 682 | "num-integer", 683 | "num-iter", 684 | "num-rational", 685 | "num-traits", 686 | ] 687 | 688 | [[package]] 689 | name = "num-bigint" 690 | version = "0.4.5" 691 | source = "registry+https://github.com/rust-lang/crates.io-index" 692 | checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" 693 | dependencies = [ 694 | "num-integer", 695 | "num-traits", 696 | ] 697 | 698 | [[package]] 699 | name = "num-complex" 700 | version = "0.4.6" 701 | source = "registry+https://github.com/rust-lang/crates.io-index" 702 | checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" 703 | dependencies = [ 704 | "num-traits", 705 | ] 706 | 707 | [[package]] 708 | name = "num-derive" 709 | version = "0.4.2" 710 | source = "registry+https://github.com/rust-lang/crates.io-index" 711 | checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" 712 | dependencies = [ 713 | "proc-macro2", 714 | "quote", 715 | "syn", 716 | ] 717 | 718 | [[package]] 719 | name = "num-integer" 720 | version = "0.1.46" 721 | source = "registry+https://github.com/rust-lang/crates.io-index" 722 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" 723 | dependencies = [ 724 | "num-traits", 725 | ] 726 | 727 | [[package]] 728 | name = "num-iter" 729 | version = "0.1.45" 730 | source = "registry+https://github.com/rust-lang/crates.io-index" 731 | checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" 732 | dependencies = [ 733 | "autocfg", 734 | "num-integer", 735 | "num-traits", 736 | ] 737 | 738 | [[package]] 739 | name = "num-rational" 740 | version = "0.4.2" 741 | source = "registry+https://github.com/rust-lang/crates.io-index" 742 | checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" 743 | dependencies = [ 744 | "num-bigint", 745 | "num-integer", 746 | "num-traits", 747 | ] 748 | 749 | [[package]] 750 | name = "num-traits" 751 | version = "0.2.19" 752 | source = "registry+https://github.com/rust-lang/crates.io-index" 753 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 754 | dependencies = [ 755 | "autocfg", 756 | ] 757 | 758 | [[package]] 759 | name = "num_cpus" 760 | version = "1.16.0" 761 | source = "registry+https://github.com/rust-lang/crates.io-index" 762 | checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" 763 | dependencies = [ 764 | "hermit-abi", 765 | "libc", 766 | ] 767 | 768 | [[package]] 769 | name = "num_enum" 770 | version = "0.7.2" 771 | source = "registry+https://github.com/rust-lang/crates.io-index" 772 | checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" 773 | dependencies = [ 774 | "num_enum_derive", 775 | ] 776 | 777 | [[package]] 778 | name = "num_enum_derive" 779 | version = "0.7.2" 780 | source = "registry+https://github.com/rust-lang/crates.io-index" 781 | checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" 782 | dependencies = [ 783 | "proc-macro-crate", 784 | "proc-macro2", 785 | "quote", 786 | "syn", 787 | ] 788 | 789 | [[package]] 790 | name = "oboe" 791 | version = "0.6.1" 792 | source = "registry+https://github.com/rust-lang/crates.io-index" 793 | checksum = "e8b61bebd49e5d43f5f8cc7ee2891c16e0f41ec7954d36bcb6c14c5e0de867fb" 794 | dependencies = [ 795 | "jni", 796 | "ndk", 797 | "ndk-context", 798 | "num-derive", 799 | "num-traits", 800 | "oboe-sys", 801 | ] 802 | 803 | [[package]] 804 | name = "oboe-sys" 805 | version = "0.6.1" 806 | source = "registry+https://github.com/rust-lang/crates.io-index" 807 | checksum = "6c8bb09a4a2b1d668170cfe0a7d5bc103f8999fb316c98099b6a9939c9f2e79d" 808 | dependencies = [ 809 | "cc", 810 | ] 811 | 812 | [[package]] 813 | name = "ogg" 814 | version = "0.7.1" 815 | source = "registry+https://github.com/rust-lang/crates.io-index" 816 | checksum = "13e571c3517af9e1729d4c63571a27edd660ade0667973bfc74a67c660c2b651" 817 | dependencies = [ 818 | "byteorder", 819 | ] 820 | 821 | [[package]] 822 | name = "ogg" 823 | version = "0.8.0" 824 | source = "registry+https://github.com/rust-lang/crates.io-index" 825 | checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e" 826 | dependencies = [ 827 | "byteorder", 828 | ] 829 | 830 | [[package]] 831 | name = "once_cell" 832 | version = "1.19.0" 833 | source = "registry+https://github.com/rust-lang/crates.io-index" 834 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 835 | 836 | [[package]] 837 | name = "percent-encoding" 838 | version = "2.3.1" 839 | source = "registry+https://github.com/rust-lang/crates.io-index" 840 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 841 | 842 | [[package]] 843 | name = "pkg-config" 844 | version = "0.3.30" 845 | source = "registry+https://github.com/rust-lang/crates.io-index" 846 | checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" 847 | 848 | [[package]] 849 | name = "prettyplease" 850 | version = "0.2.20" 851 | source = "registry+https://github.com/rust-lang/crates.io-index" 852 | checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" 853 | dependencies = [ 854 | "proc-macro2", 855 | "syn", 856 | ] 857 | 858 | [[package]] 859 | name = "proc-macro-crate" 860 | version = "3.1.0" 861 | source = "registry+https://github.com/rust-lang/crates.io-index" 862 | checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" 863 | dependencies = [ 864 | "toml_edit", 865 | ] 866 | 867 | [[package]] 868 | name = "proc-macro2" 869 | version = "1.0.86" 870 | source = "registry+https://github.com/rust-lang/crates.io-index" 871 | checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" 872 | dependencies = [ 873 | "unicode-ident", 874 | ] 875 | 876 | [[package]] 877 | name = "quote" 878 | version = "1.0.36" 879 | source = "registry+https://github.com/rust-lang/crates.io-index" 880 | checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" 881 | dependencies = [ 882 | "proc-macro2", 883 | ] 884 | 885 | [[package]] 886 | name = "regex" 887 | version = "1.10.5" 888 | source = "registry+https://github.com/rust-lang/crates.io-index" 889 | checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" 890 | dependencies = [ 891 | "aho-corasick", 892 | "memchr", 893 | "regex-automata", 894 | "regex-syntax", 895 | ] 896 | 897 | [[package]] 898 | name = "regex-automata" 899 | version = "0.4.7" 900 | source = "registry+https://github.com/rust-lang/crates.io-index" 901 | checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" 902 | dependencies = [ 903 | "aho-corasick", 904 | "memchr", 905 | "regex-syntax", 906 | ] 907 | 908 | [[package]] 909 | name = "regex-syntax" 910 | version = "0.8.4" 911 | source = "registry+https://github.com/rust-lang/crates.io-index" 912 | checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" 913 | 914 | [[package]] 915 | name = "ring" 916 | version = "0.17.8" 917 | source = "registry+https://github.com/rust-lang/crates.io-index" 918 | checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" 919 | dependencies = [ 920 | "cc", 921 | "cfg-if", 922 | "getrandom", 923 | "libc", 924 | "spin", 925 | "untrusted", 926 | "windows-sys 0.52.0", 927 | ] 928 | 929 | [[package]] 930 | name = "rodio" 931 | version = "0.18.1" 932 | source = "registry+https://github.com/rust-lang/crates.io-index" 933 | checksum = "d1fceb9d127d515af1586d8d0cc601e1245bdb0af38e75c865a156290184f5b3" 934 | dependencies = [ 935 | "claxon", 936 | "cpal", 937 | "hound", 938 | "lewton 0.10.2", 939 | "minimp3_fixed", 940 | "symphonia", 941 | "thiserror", 942 | ] 943 | 944 | [[package]] 945 | name = "rustc-hash" 946 | version = "1.1.0" 947 | source = "registry+https://github.com/rust-lang/crates.io-index" 948 | checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" 949 | 950 | [[package]] 951 | name = "rustix" 952 | version = "0.38.34" 953 | source = "registry+https://github.com/rust-lang/crates.io-index" 954 | checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" 955 | dependencies = [ 956 | "bitflags 2.5.0", 957 | "errno", 958 | "libc", 959 | "linux-raw-sys", 960 | "windows-sys 0.52.0", 961 | ] 962 | 963 | [[package]] 964 | name = "rustls" 965 | version = "0.22.4" 966 | source = "registry+https://github.com/rust-lang/crates.io-index" 967 | checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" 968 | dependencies = [ 969 | "log", 970 | "ring", 971 | "rustls-pki-types", 972 | "rustls-webpki", 973 | "subtle", 974 | "zeroize", 975 | ] 976 | 977 | [[package]] 978 | name = "rustls-pki-types" 979 | version = "1.7.0" 980 | source = "registry+https://github.com/rust-lang/crates.io-index" 981 | checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" 982 | 983 | [[package]] 984 | name = "rustls-webpki" 985 | version = "0.102.4" 986 | source = "registry+https://github.com/rust-lang/crates.io-index" 987 | checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" 988 | dependencies = [ 989 | "ring", 990 | "rustls-pki-types", 991 | "untrusted", 992 | ] 993 | 994 | [[package]] 995 | name = "rustversion" 996 | version = "1.0.17" 997 | source = "registry+https://github.com/rust-lang/crates.io-index" 998 | checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" 999 | 1000 | [[package]] 1001 | name = "ryu" 1002 | version = "1.0.18" 1003 | source = "registry+https://github.com/rust-lang/crates.io-index" 1004 | checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" 1005 | 1006 | [[package]] 1007 | name = "same-file" 1008 | version = "1.0.6" 1009 | source = "registry+https://github.com/rust-lang/crates.io-index" 1010 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 1011 | dependencies = [ 1012 | "winapi-util", 1013 | ] 1014 | 1015 | [[package]] 1016 | name = "serde" 1017 | version = "1.0.203" 1018 | source = "registry+https://github.com/rust-lang/crates.io-index" 1019 | checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" 1020 | dependencies = [ 1021 | "serde_derive", 1022 | ] 1023 | 1024 | [[package]] 1025 | name = "serde_derive" 1026 | version = "1.0.203" 1027 | source = "registry+https://github.com/rust-lang/crates.io-index" 1028 | checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" 1029 | dependencies = [ 1030 | "proc-macro2", 1031 | "quote", 1032 | "syn", 1033 | ] 1034 | 1035 | [[package]] 1036 | name = "serde_json" 1037 | version = "1.0.117" 1038 | source = "registry+https://github.com/rust-lang/crates.io-index" 1039 | checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" 1040 | dependencies = [ 1041 | "itoa", 1042 | "ryu", 1043 | "serde", 1044 | ] 1045 | 1046 | [[package]] 1047 | name = "shlex" 1048 | version = "1.3.0" 1049 | source = "registry+https://github.com/rust-lang/crates.io-index" 1050 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 1051 | 1052 | [[package]] 1053 | name = "slice-ring-buffer" 1054 | version = "0.3.3" 1055 | source = "registry+https://github.com/rust-lang/crates.io-index" 1056 | checksum = "7081c7e452cb62f5f0c32edd4e265391bdbb23e90905df8bb88a23d3b5166b77" 1057 | dependencies = [ 1058 | "libc", 1059 | "mach2", 1060 | "winapi", 1061 | ] 1062 | 1063 | [[package]] 1064 | name = "smallvec" 1065 | version = "0.6.14" 1066 | source = "registry+https://github.com/rust-lang/crates.io-index" 1067 | checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" 1068 | dependencies = [ 1069 | "maybe-uninit", 1070 | ] 1071 | 1072 | [[package]] 1073 | name = "spin" 1074 | version = "0.9.8" 1075 | source = "registry+https://github.com/rust-lang/crates.io-index" 1076 | checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" 1077 | 1078 | [[package]] 1079 | name = "strum" 1080 | version = "0.26.3" 1081 | source = "registry+https://github.com/rust-lang/crates.io-index" 1082 | checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" 1083 | dependencies = [ 1084 | "strum_macros", 1085 | ] 1086 | 1087 | [[package]] 1088 | name = "strum_macros" 1089 | version = "0.26.4" 1090 | source = "registry+https://github.com/rust-lang/crates.io-index" 1091 | checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" 1092 | dependencies = [ 1093 | "heck", 1094 | "proc-macro2", 1095 | "quote", 1096 | "rustversion", 1097 | "syn", 1098 | ] 1099 | 1100 | [[package]] 1101 | name = "subtle" 1102 | version = "2.6.0" 1103 | source = "registry+https://github.com/rust-lang/crates.io-index" 1104 | checksum = "0d0208408ba0c3df17ed26eb06992cb1a1268d41b2c0e12e65203fbe3972cee5" 1105 | 1106 | [[package]] 1107 | name = "symphonia" 1108 | version = "0.5.4" 1109 | source = "registry+https://github.com/rust-lang/crates.io-index" 1110 | checksum = "815c942ae7ee74737bb00f965fa5b5a2ac2ce7b6c01c0cc169bbeaf7abd5f5a9" 1111 | dependencies = [ 1112 | "lazy_static", 1113 | "symphonia-bundle-flac", 1114 | "symphonia-bundle-mp3", 1115 | "symphonia-codec-aac", 1116 | "symphonia-codec-adpcm", 1117 | "symphonia-codec-pcm", 1118 | "symphonia-codec-vorbis", 1119 | "symphonia-core", 1120 | "symphonia-format-isomp4", 1121 | "symphonia-format-riff", 1122 | "symphonia-metadata", 1123 | ] 1124 | 1125 | [[package]] 1126 | name = "symphonia-bundle-flac" 1127 | version = "0.5.4" 1128 | source = "registry+https://github.com/rust-lang/crates.io-index" 1129 | checksum = "72e34f34298a7308d4397a6c7fbf5b84c5d491231ce3dd379707ba673ab3bd97" 1130 | dependencies = [ 1131 | "log", 1132 | "symphonia-core", 1133 | "symphonia-metadata", 1134 | "symphonia-utils-xiph", 1135 | ] 1136 | 1137 | [[package]] 1138 | name = "symphonia-bundle-mp3" 1139 | version = "0.5.4" 1140 | source = "registry+https://github.com/rust-lang/crates.io-index" 1141 | checksum = "c01c2aae70f0f1fb096b6f0ff112a930b1fb3626178fba3ae68b09dce71706d4" 1142 | dependencies = [ 1143 | "lazy_static", 1144 | "log", 1145 | "symphonia-core", 1146 | "symphonia-metadata", 1147 | ] 1148 | 1149 | [[package]] 1150 | name = "symphonia-codec-aac" 1151 | version = "0.5.4" 1152 | source = "registry+https://github.com/rust-lang/crates.io-index" 1153 | checksum = "cdbf25b545ad0d3ee3e891ea643ad115aff4ca92f6aec472086b957a58522f70" 1154 | dependencies = [ 1155 | "lazy_static", 1156 | "log", 1157 | "symphonia-core", 1158 | ] 1159 | 1160 | [[package]] 1161 | name = "symphonia-codec-adpcm" 1162 | version = "0.5.4" 1163 | source = "registry+https://github.com/rust-lang/crates.io-index" 1164 | checksum = "c94e1feac3327cd616e973d5be69ad36b3945f16b06f19c6773fc3ac0b426a0f" 1165 | dependencies = [ 1166 | "log", 1167 | "symphonia-core", 1168 | ] 1169 | 1170 | [[package]] 1171 | name = "symphonia-codec-pcm" 1172 | version = "0.5.4" 1173 | source = "registry+https://github.com/rust-lang/crates.io-index" 1174 | checksum = "f395a67057c2ebc5e84d7bb1be71cce1a7ba99f64e0f0f0e303a03f79116f89b" 1175 | dependencies = [ 1176 | "log", 1177 | "symphonia-core", 1178 | ] 1179 | 1180 | [[package]] 1181 | name = "symphonia-codec-vorbis" 1182 | version = "0.5.4" 1183 | source = "registry+https://github.com/rust-lang/crates.io-index" 1184 | checksum = "5a98765fb46a0a6732b007f7e2870c2129b6f78d87db7987e6533c8f164a9f30" 1185 | dependencies = [ 1186 | "log", 1187 | "symphonia-core", 1188 | "symphonia-utils-xiph", 1189 | ] 1190 | 1191 | [[package]] 1192 | name = "symphonia-core" 1193 | version = "0.5.4" 1194 | source = "registry+https://github.com/rust-lang/crates.io-index" 1195 | checksum = "798306779e3dc7d5231bd5691f5a813496dc79d3f56bf82e25789f2094e022c3" 1196 | dependencies = [ 1197 | "arrayvec", 1198 | "bitflags 1.3.2", 1199 | "bytemuck", 1200 | "lazy_static", 1201 | "log", 1202 | ] 1203 | 1204 | [[package]] 1205 | name = "symphonia-format-isomp4" 1206 | version = "0.5.4" 1207 | source = "registry+https://github.com/rust-lang/crates.io-index" 1208 | checksum = "abfdf178d697e50ce1e5d9b982ba1b94c47218e03ec35022d9f0e071a16dc844" 1209 | dependencies = [ 1210 | "encoding_rs", 1211 | "log", 1212 | "symphonia-core", 1213 | "symphonia-metadata", 1214 | "symphonia-utils-xiph", 1215 | ] 1216 | 1217 | [[package]] 1218 | name = "symphonia-format-riff" 1219 | version = "0.5.4" 1220 | source = "registry+https://github.com/rust-lang/crates.io-index" 1221 | checksum = "05f7be232f962f937f4b7115cbe62c330929345434c834359425e043bfd15f50" 1222 | dependencies = [ 1223 | "extended", 1224 | "log", 1225 | "symphonia-core", 1226 | "symphonia-metadata", 1227 | ] 1228 | 1229 | [[package]] 1230 | name = "symphonia-metadata" 1231 | version = "0.5.4" 1232 | source = "registry+https://github.com/rust-lang/crates.io-index" 1233 | checksum = "bc622b9841a10089c5b18e99eb904f4341615d5aa55bbf4eedde1be721a4023c" 1234 | dependencies = [ 1235 | "encoding_rs", 1236 | "lazy_static", 1237 | "log", 1238 | "symphonia-core", 1239 | ] 1240 | 1241 | [[package]] 1242 | name = "symphonia-utils-xiph" 1243 | version = "0.5.4" 1244 | source = "registry+https://github.com/rust-lang/crates.io-index" 1245 | checksum = "484472580fa49991afda5f6550ece662237b00c6f562c7d9638d1b086ed010fe" 1246 | dependencies = [ 1247 | "symphonia-core", 1248 | "symphonia-metadata", 1249 | ] 1250 | 1251 | [[package]] 1252 | name = "syn" 1253 | version = "2.0.68" 1254 | source = "registry+https://github.com/rust-lang/crates.io-index" 1255 | checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" 1256 | dependencies = [ 1257 | "proc-macro2", 1258 | "quote", 1259 | "unicode-ident", 1260 | ] 1261 | 1262 | [[package]] 1263 | name = "thiserror" 1264 | version = "1.0.61" 1265 | source = "registry+https://github.com/rust-lang/crates.io-index" 1266 | checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" 1267 | dependencies = [ 1268 | "thiserror-impl", 1269 | ] 1270 | 1271 | [[package]] 1272 | name = "thiserror-impl" 1273 | version = "1.0.61" 1274 | source = "registry+https://github.com/rust-lang/crates.io-index" 1275 | checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" 1276 | dependencies = [ 1277 | "proc-macro2", 1278 | "quote", 1279 | "syn", 1280 | ] 1281 | 1282 | [[package]] 1283 | name = "tinyvec" 1284 | version = "1.6.0" 1285 | source = "registry+https://github.com/rust-lang/crates.io-index" 1286 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 1287 | dependencies = [ 1288 | "tinyvec_macros", 1289 | ] 1290 | 1291 | [[package]] 1292 | name = "tinyvec_macros" 1293 | version = "0.1.1" 1294 | source = "registry+https://github.com/rust-lang/crates.io-index" 1295 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 1296 | 1297 | [[package]] 1298 | name = "toml_datetime" 1299 | version = "0.6.6" 1300 | source = "registry+https://github.com/rust-lang/crates.io-index" 1301 | checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" 1302 | 1303 | [[package]] 1304 | name = "toml_edit" 1305 | version = "0.21.1" 1306 | source = "registry+https://github.com/rust-lang/crates.io-index" 1307 | checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" 1308 | dependencies = [ 1309 | "indexmap", 1310 | "toml_datetime", 1311 | "winnow", 1312 | ] 1313 | 1314 | [[package]] 1315 | name = "unicode-bidi" 1316 | version = "0.3.15" 1317 | source = "registry+https://github.com/rust-lang/crates.io-index" 1318 | checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" 1319 | 1320 | [[package]] 1321 | name = "unicode-ident" 1322 | version = "1.0.12" 1323 | source = "registry+https://github.com/rust-lang/crates.io-index" 1324 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 1325 | 1326 | [[package]] 1327 | name = "unicode-normalization" 1328 | version = "0.1.23" 1329 | source = "registry+https://github.com/rust-lang/crates.io-index" 1330 | checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" 1331 | dependencies = [ 1332 | "tinyvec", 1333 | ] 1334 | 1335 | [[package]] 1336 | name = "untrusted" 1337 | version = "0.9.0" 1338 | source = "registry+https://github.com/rust-lang/crates.io-index" 1339 | checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" 1340 | 1341 | [[package]] 1342 | name = "ureq" 1343 | version = "2.9.7" 1344 | source = "registry+https://github.com/rust-lang/crates.io-index" 1345 | checksum = "d11a831e3c0b56e438a28308e7c810799e3c118417f342d30ecec080105395cd" 1346 | dependencies = [ 1347 | "base64", 1348 | "flate2", 1349 | "log", 1350 | "once_cell", 1351 | "rustls", 1352 | "rustls-pki-types", 1353 | "rustls-webpki", 1354 | "url", 1355 | "webpki-roots", 1356 | ] 1357 | 1358 | [[package]] 1359 | name = "url" 1360 | version = "2.5.2" 1361 | source = "registry+https://github.com/rust-lang/crates.io-index" 1362 | checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" 1363 | dependencies = [ 1364 | "form_urlencoded", 1365 | "idna", 1366 | "percent-encoding", 1367 | ] 1368 | 1369 | [[package]] 1370 | name = "walkdir" 1371 | version = "2.5.0" 1372 | source = "registry+https://github.com/rust-lang/crates.io-index" 1373 | checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" 1374 | dependencies = [ 1375 | "same-file", 1376 | "winapi-util", 1377 | ] 1378 | 1379 | [[package]] 1380 | name = "wasi" 1381 | version = "0.11.0+wasi-snapshot-preview1" 1382 | source = "registry+https://github.com/rust-lang/crates.io-index" 1383 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1384 | 1385 | [[package]] 1386 | name = "wasm-bindgen" 1387 | version = "0.2.92" 1388 | source = "registry+https://github.com/rust-lang/crates.io-index" 1389 | checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" 1390 | dependencies = [ 1391 | "cfg-if", 1392 | "wasm-bindgen-macro", 1393 | ] 1394 | 1395 | [[package]] 1396 | name = "wasm-bindgen-backend" 1397 | version = "0.2.92" 1398 | source = "registry+https://github.com/rust-lang/crates.io-index" 1399 | checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" 1400 | dependencies = [ 1401 | "bumpalo", 1402 | "log", 1403 | "once_cell", 1404 | "proc-macro2", 1405 | "quote", 1406 | "syn", 1407 | "wasm-bindgen-shared", 1408 | ] 1409 | 1410 | [[package]] 1411 | name = "wasm-bindgen-futures" 1412 | version = "0.4.42" 1413 | source = "registry+https://github.com/rust-lang/crates.io-index" 1414 | checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" 1415 | dependencies = [ 1416 | "cfg-if", 1417 | "js-sys", 1418 | "wasm-bindgen", 1419 | "web-sys", 1420 | ] 1421 | 1422 | [[package]] 1423 | name = "wasm-bindgen-macro" 1424 | version = "0.2.92" 1425 | source = "registry+https://github.com/rust-lang/crates.io-index" 1426 | checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" 1427 | dependencies = [ 1428 | "quote", 1429 | "wasm-bindgen-macro-support", 1430 | ] 1431 | 1432 | [[package]] 1433 | name = "wasm-bindgen-macro-support" 1434 | version = "0.2.92" 1435 | source = "registry+https://github.com/rust-lang/crates.io-index" 1436 | checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" 1437 | dependencies = [ 1438 | "proc-macro2", 1439 | "quote", 1440 | "syn", 1441 | "wasm-bindgen-backend", 1442 | "wasm-bindgen-shared", 1443 | ] 1444 | 1445 | [[package]] 1446 | name = "wasm-bindgen-shared" 1447 | version = "0.2.92" 1448 | source = "registry+https://github.com/rust-lang/crates.io-index" 1449 | checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" 1450 | 1451 | [[package]] 1452 | name = "web-sys" 1453 | version = "0.3.69" 1454 | source = "registry+https://github.com/rust-lang/crates.io-index" 1455 | checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" 1456 | dependencies = [ 1457 | "js-sys", 1458 | "wasm-bindgen", 1459 | ] 1460 | 1461 | [[package]] 1462 | name = "webpki-roots" 1463 | version = "0.26.3" 1464 | source = "registry+https://github.com/rust-lang/crates.io-index" 1465 | checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" 1466 | dependencies = [ 1467 | "rustls-pki-types", 1468 | ] 1469 | 1470 | [[package]] 1471 | name = "which" 1472 | version = "4.4.2" 1473 | source = "registry+https://github.com/rust-lang/crates.io-index" 1474 | checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" 1475 | dependencies = [ 1476 | "either", 1477 | "home", 1478 | "once_cell", 1479 | "rustix", 1480 | ] 1481 | 1482 | [[package]] 1483 | name = "whisper-rs" 1484 | version = "0.11.1" 1485 | source = "registry+https://github.com/rust-lang/crates.io-index" 1486 | checksum = "ed7a191078e189d96d029244ab1dff159775adec71dc89a222e9bb9d21a7d161" 1487 | dependencies = [ 1488 | "log", 1489 | "whisper-rs-sys", 1490 | ] 1491 | 1492 | [[package]] 1493 | name = "whisper-rs-sys" 1494 | version = "0.9.0" 1495 | source = "registry+https://github.com/rust-lang/crates.io-index" 1496 | checksum = "2834f4ca6472b02748c6c282a60cea538f962428f79e685c3205a08efd711336" 1497 | dependencies = [ 1498 | "bindgen", 1499 | "cfg-if", 1500 | "cmake", 1501 | "fs_extra", 1502 | ] 1503 | 1504 | [[package]] 1505 | name = "winapi" 1506 | version = "0.3.9" 1507 | source = "registry+https://github.com/rust-lang/crates.io-index" 1508 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1509 | dependencies = [ 1510 | "winapi-i686-pc-windows-gnu", 1511 | "winapi-x86_64-pc-windows-gnu", 1512 | ] 1513 | 1514 | [[package]] 1515 | name = "winapi-i686-pc-windows-gnu" 1516 | version = "0.4.0" 1517 | source = "registry+https://github.com/rust-lang/crates.io-index" 1518 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1519 | 1520 | [[package]] 1521 | name = "winapi-util" 1522 | version = "0.1.8" 1523 | source = "registry+https://github.com/rust-lang/crates.io-index" 1524 | checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" 1525 | dependencies = [ 1526 | "windows-sys 0.52.0", 1527 | ] 1528 | 1529 | [[package]] 1530 | name = "winapi-x86_64-pc-windows-gnu" 1531 | version = "0.4.0" 1532 | source = "registry+https://github.com/rust-lang/crates.io-index" 1533 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1534 | 1535 | [[package]] 1536 | name = "windows" 1537 | version = "0.54.0" 1538 | source = "registry+https://github.com/rust-lang/crates.io-index" 1539 | checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" 1540 | dependencies = [ 1541 | "windows-core", 1542 | "windows-targets 0.52.5", 1543 | ] 1544 | 1545 | [[package]] 1546 | name = "windows-core" 1547 | version = "0.54.0" 1548 | source = "registry+https://github.com/rust-lang/crates.io-index" 1549 | checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" 1550 | dependencies = [ 1551 | "windows-result", 1552 | "windows-targets 0.52.5", 1553 | ] 1554 | 1555 | [[package]] 1556 | name = "windows-result" 1557 | version = "0.1.2" 1558 | source = "registry+https://github.com/rust-lang/crates.io-index" 1559 | checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" 1560 | dependencies = [ 1561 | "windows-targets 0.52.5", 1562 | ] 1563 | 1564 | [[package]] 1565 | name = "windows-sys" 1566 | version = "0.45.0" 1567 | source = "registry+https://github.com/rust-lang/crates.io-index" 1568 | checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" 1569 | dependencies = [ 1570 | "windows-targets 0.42.2", 1571 | ] 1572 | 1573 | [[package]] 1574 | name = "windows-sys" 1575 | version = "0.52.0" 1576 | source = "registry+https://github.com/rust-lang/crates.io-index" 1577 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 1578 | dependencies = [ 1579 | "windows-targets 0.52.5", 1580 | ] 1581 | 1582 | [[package]] 1583 | name = "windows-targets" 1584 | version = "0.42.2" 1585 | source = "registry+https://github.com/rust-lang/crates.io-index" 1586 | checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" 1587 | dependencies = [ 1588 | "windows_aarch64_gnullvm 0.42.2", 1589 | "windows_aarch64_msvc 0.42.2", 1590 | "windows_i686_gnu 0.42.2", 1591 | "windows_i686_msvc 0.42.2", 1592 | "windows_x86_64_gnu 0.42.2", 1593 | "windows_x86_64_gnullvm 0.42.2", 1594 | "windows_x86_64_msvc 0.42.2", 1595 | ] 1596 | 1597 | [[package]] 1598 | name = "windows-targets" 1599 | version = "0.52.5" 1600 | source = "registry+https://github.com/rust-lang/crates.io-index" 1601 | checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" 1602 | dependencies = [ 1603 | "windows_aarch64_gnullvm 0.52.5", 1604 | "windows_aarch64_msvc 0.52.5", 1605 | "windows_i686_gnu 0.52.5", 1606 | "windows_i686_gnullvm", 1607 | "windows_i686_msvc 0.52.5", 1608 | "windows_x86_64_gnu 0.52.5", 1609 | "windows_x86_64_gnullvm 0.52.5", 1610 | "windows_x86_64_msvc 0.52.5", 1611 | ] 1612 | 1613 | [[package]] 1614 | name = "windows_aarch64_gnullvm" 1615 | version = "0.42.2" 1616 | source = "registry+https://github.com/rust-lang/crates.io-index" 1617 | checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" 1618 | 1619 | [[package]] 1620 | name = "windows_aarch64_gnullvm" 1621 | version = "0.52.5" 1622 | source = "registry+https://github.com/rust-lang/crates.io-index" 1623 | checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" 1624 | 1625 | [[package]] 1626 | name = "windows_aarch64_msvc" 1627 | version = "0.42.2" 1628 | source = "registry+https://github.com/rust-lang/crates.io-index" 1629 | checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" 1630 | 1631 | [[package]] 1632 | name = "windows_aarch64_msvc" 1633 | version = "0.52.5" 1634 | source = "registry+https://github.com/rust-lang/crates.io-index" 1635 | checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" 1636 | 1637 | [[package]] 1638 | name = "windows_i686_gnu" 1639 | version = "0.42.2" 1640 | source = "registry+https://github.com/rust-lang/crates.io-index" 1641 | checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" 1642 | 1643 | [[package]] 1644 | name = "windows_i686_gnu" 1645 | version = "0.52.5" 1646 | source = "registry+https://github.com/rust-lang/crates.io-index" 1647 | checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" 1648 | 1649 | [[package]] 1650 | name = "windows_i686_gnullvm" 1651 | version = "0.52.5" 1652 | source = "registry+https://github.com/rust-lang/crates.io-index" 1653 | checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" 1654 | 1655 | [[package]] 1656 | name = "windows_i686_msvc" 1657 | version = "0.42.2" 1658 | source = "registry+https://github.com/rust-lang/crates.io-index" 1659 | checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" 1660 | 1661 | [[package]] 1662 | name = "windows_i686_msvc" 1663 | version = "0.52.5" 1664 | source = "registry+https://github.com/rust-lang/crates.io-index" 1665 | checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" 1666 | 1667 | [[package]] 1668 | name = "windows_x86_64_gnu" 1669 | version = "0.42.2" 1670 | source = "registry+https://github.com/rust-lang/crates.io-index" 1671 | checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" 1672 | 1673 | [[package]] 1674 | name = "windows_x86_64_gnu" 1675 | version = "0.52.5" 1676 | source = "registry+https://github.com/rust-lang/crates.io-index" 1677 | checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" 1678 | 1679 | [[package]] 1680 | name = "windows_x86_64_gnullvm" 1681 | version = "0.42.2" 1682 | source = "registry+https://github.com/rust-lang/crates.io-index" 1683 | checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" 1684 | 1685 | [[package]] 1686 | name = "windows_x86_64_gnullvm" 1687 | version = "0.52.5" 1688 | source = "registry+https://github.com/rust-lang/crates.io-index" 1689 | checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" 1690 | 1691 | [[package]] 1692 | name = "windows_x86_64_msvc" 1693 | version = "0.42.2" 1694 | source = "registry+https://github.com/rust-lang/crates.io-index" 1695 | checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" 1696 | 1697 | [[package]] 1698 | name = "windows_x86_64_msvc" 1699 | version = "0.52.5" 1700 | source = "registry+https://github.com/rust-lang/crates.io-index" 1701 | checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" 1702 | 1703 | [[package]] 1704 | name = "winnow" 1705 | version = "0.5.40" 1706 | source = "registry+https://github.com/rust-lang/crates.io-index" 1707 | checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" 1708 | dependencies = [ 1709 | "memchr", 1710 | ] 1711 | 1712 | [[package]] 1713 | name = "zeroize" 1714 | version = "1.8.1" 1715 | source = "registry+https://github.com/rust-lang/crates.io-index" 1716 | checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" 1717 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mutter" 3 | version = "0.2.0" 4 | edition = "2021" 5 | license = "MIT OR Apache-2.0" 6 | description = "Easy-to-use bindings to the Whisper.cpp machine learning transcription library!" 7 | homepage = "https://github.com/sigaloid/mutter" 8 | repository = "https://github.com/sigaloid/mutter" 9 | documentation = "https://docs.rs/mutter" 10 | keywords = ["whisper", "openai", "transcription", "machine-learning"] 11 | categories = ["science", "multimedia::audio", "accessibility"] 12 | 13 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 14 | 15 | [dependencies] 16 | audrey = "0.3.0" 17 | log = "0.4.21" 18 | num = "0.4.3" 19 | num_cpus = "1.16.0" 20 | rodio = { version = "0.18.1" } 21 | serde = { version = "1.0.203", features = ["derive"] } 22 | serde_json = "1.0.117" 23 | strum = { version = "0.26.2", features = ["derive"] } 24 | ureq = "2.9.7" 25 | whisper-rs = { version = "0.11", features = ["whisper-cpp-log"] } 26 | 27 | [features] 28 | default = [] 29 | 30 | simd = [] 31 | coreml = ["whisper-rs/coreml"] 32 | cuda = ["whisper-rs/cuda"] 33 | opencl = ["whisper-rs/opencl"] 34 | test-with-tiny-model = [] 35 | 36 | symphonia-aac = ["rodio/symphonia-aac"] 37 | symphonia-all = ["rodio/symphonia-all"] 38 | symphonia-flac = ["rodio/symphonia-flac"] 39 | symphonia-isomp4 = ["rodio/symphonia-isomp4"] 40 | symphonia-mp3 = ["rodio/symphonia-mp3"] 41 | symphonia-vorbis = ["rodio/symphonia-vorbis"] 42 | symphonia-wav = ["rodio/symphonia-wav"] 43 | minimp3 = ["rodio/minimp3"] 44 | 45 | [dev-dependencies] 46 | glob = "0.3.1" 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mutter 2 | 3 | Mutter is a Rust library that makes transcription with the OpenAI Whisper models, easy. 4 | 5 | ```rust 6 | use mutter::{Model, ModelType}; 7 | 8 | let model = Model::download(&ModelType::BaseEn).unwrap(); 9 | let mp3: Vec = download_mp3(); 10 | let transcription = model.transcribe_audio(mp3, false, false, None).unwrap(); 11 | println!("{}", transcription.as_text()); 12 | println!("{}", transcription.as_srt()); 13 | ``` 14 | 15 | # Codecs 16 | 17 | Mutter supports all codecs that Rodio, the audio backend, supports. 18 | * MP3 (Symphonia) 19 | * WAV (Hound) 20 | * OGG Vorbis (lewton) 21 | * FLAC (claxon) 22 | 23 | Alternatively, enable the `minimp3` feature to use the minimp3 backend. 24 | 25 | You can also enable any of these features to enable the optional symphonia backend for these features. 26 | 27 | 28 | ```toml 29 | symphonia-aac = ["rodio/symphonia-aac"] 30 | symphonia-all = ["rodio/symphonia-all"] 31 | symphonia-flac = ["rodio/symphonia-flac"] 32 | symphonia-isomp4 = ["rodio/symphonia-isomp4"] 33 | symphonia-mp3 = ["rodio/symphonia-mp3"] 34 | symphonia-vorbis = ["rodio/symphonia-vorbis"] 35 | symphonia-wav = ["rodio/symphonia-wav"] 36 | ``` 37 | 38 | # About this crate 39 | 40 | This crate is largely a thin wrapper around whisper-rs, that simply opens up transcription to any file format (it handles conversion via `rodio`). Whisper-rs handles the actual bindings to the Whisper.cpp library. I wrote this because I didn't want to reimplement the conversion + re-encoding to 16-bit mono PCM WAV every single time I wanted to use Whisper in a new Rust library, and my initial implementation relying on `ffmpeg` existing on the target device was not at all compatible. While the targets are limited by whisper-rs and by extension whisper.cpp's supported targets, and while ffmpeg is pretty universal, I wanted to portable-ify as much as possible. In addition, my university's compute clusters don't have FFmpeg by default. 41 | 42 | Oh, and I added a download function that will load the model at runtime. Be warned, the models can be as large as 3GB! 43 | 44 | # Transcoding 45 | 46 | This crate relies on rodio to perform the transcoding. In order to reduce background noise and optimize for human speech, it also applies a 200hz low pass filter and a 3000hz high pass filter. I wanted to apply more advanced voice filters, like FFmpeg's `arnndn`, but was unable to do so while keeping it within the Rodio ecosystem for simplicity. 47 | 48 | # Future work 49 | 50 | I would love to extend this crate to have more advanced noise reduction. Outside of that, I'd love to explore any more opinionated modifications to the audio, like implementing a VAD, but I'm yet to find any crates in the ecosystem yet (and might not have the time to implement it if I did). 51 | 52 | # Credits 53 | 54 | @tazz4843 for their wonderful work on the [whisper-rs](https://github.com/tazz4843/whisper-rs) bindings. This crate essentially adds just two features above it: transcoding, and downloading models. 55 | 56 | ### Show appreciation 57 | 58 | Want to say thanks for this library? Just click the button below and leave a brief note. It would make my day :) 59 | 60 | [![Click me to show appreciation](https://img.shields.io/badge/Say%20Thanks-%F0%9F%A6%80%F0%9F%A6%80%F0%9F%A6%80-1EAEDB.svg)](https://saythanks.io/to/sigaloid) -------------------------------------------------------------------------------- /samples/3kliks-cut.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigaloid/mutter/1bd82f7b2b78ea2e958c3b1793b71f86423cc340/samples/3kliks-cut.mp3 -------------------------------------------------------------------------------- /samples/jfk.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigaloid/mutter/1bd82f7b2b78ea2e958c3b1793b71f86423cc340/samples/jfk.wav -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # Mutter 2 | //! 3 | //! Mutter is a Rust library that makes transcription with the Whisper transcription models 4 | //! easy and accesible in Rust. It's a wrapper around [whisper-rs](https://github.com/tazz4843/whisper-rs) which is in turn 5 | //! a wrapper around [whisper.cpp](https://github.com/ggerganov/whisper.cpp). 6 | //! 7 | //! ```no_run 8 | //! use mutter::{Model, ModelType}; 9 | //! 10 | //! let model = Model::download(&ModelType::BaseEn).unwrap(); 11 | //! let mp3: Vec = download_mp3(); // Your own function to download audio 12 | //! let translate = false; 13 | //! let individual_word_timestamps = false; 14 | //! let threads = Some(8); 15 | //! let transcription = model.transcribe_audio(mp3, translate, individual_word_timestamps, threads).unwrap(); 16 | //! println!("{}", transcription.as_text()); 17 | //! println!("{}", transcription.as_srt()); 18 | //! ``` 19 | //! 20 | //! # Codecs 21 | //! 22 | //! Mutter supports all codecs that Rodio, the audio backend, supports. 23 | //! * MP3 (Symphonia) 24 | //! * WAV (Hound) 25 | //! * OGG Vorbis (lewton) 26 | //! * FLAC (claxon) 27 | //! 28 | //! Alternatively, enable the `minimp3` feature to use the minimp3 backend. 29 | //! 30 | //! You can also enable any of these features to enable the optional symphonia backend for these features. 31 | //! 32 | //! 33 | //! ```toml 34 | //! symphonia-aac = ["rodio/symphonia-aac"] 35 | //! symphonia-all = ["rodio/symphonia-all"] 36 | //! symphonia-flac = ["rodio/symphonia-flac"] 37 | //! symphonia-isomp4 = ["rodio/symphonia-isomp4"] 38 | //! symphonia-mp3 = ["rodio/symphonia-mp3"] 39 | //! symphonia-vorbis = ["rodio/symphonia-vorbis"] 40 | //! symphonia-wav = ["rodio/symphonia-wav"] 41 | //! ``` 42 | //! 43 | use std::{fmt::Display, time::Instant}; 44 | 45 | use log::{info, trace}; 46 | use strum::EnumIter; 47 | use transcript::{Transcript, Utterance}; 48 | use whisper_rs::{ 49 | FullParams, SamplingStrategy, WhisperContext, WhisperContextParameters, WhisperError, 50 | }; 51 | 52 | mod tests; 53 | mod transcode; 54 | pub mod transcript; 55 | 56 | /// Model struct. Can be constructed with [`Model::new`] or [`Model::download`]. 57 | /// Contains the Whisper model and its context. 58 | pub struct Model { 59 | context: WhisperContext, 60 | } 61 | 62 | impl Model { 63 | /// Creates a new model from a model path. Must be a path to a valid Whisper model, 64 | /// in GGML format, that is compatible with Whisper.cpp. 65 | /// # Arguments 66 | /// - `path`: Path to the model. 67 | /// # Errors 68 | /// - [`WhisperError`] 69 | pub fn new(path: &str) -> Result { 70 | trace!("Loading model {}", path); 71 | // Sanity check - make sure the path exists 72 | let path_converted = std::path::Path::new(path); 73 | if !path_converted.exists() { 74 | return Err(WhisperError::InitError); 75 | } 76 | 77 | let params: WhisperContextParameters = WhisperContextParameters::default(); 78 | Ok({ 79 | Self { 80 | context: WhisperContext::new_with_params(path, params)?, 81 | } 82 | }) 83 | } 84 | 85 | /// Creates a new model and downloads the specified model type from huggingface. 86 | /// # Arguments 87 | /// - `model`: [`ModelType`]. 88 | /// # Errors 89 | /// - [`ModelError`] 90 | /// - [`ModelError::WhisperError`], 91 | /// - [`ModelError::DownloadError`], 92 | /// - [`ModelError::IoError`], 93 | /// # Panics 94 | /// This function shouldn't panic, but may due to the underlying -sys bindings. 95 | /// It shouldn't panic within _this_ crate. 96 | 97 | pub fn download(model: &ModelType) -> Result { 98 | trace!("Downloading model {}", model); 99 | let resp = ureq::get(&model.to_string()) 100 | .call() 101 | .map_err(|e| ModelError::DownloadError(Box::new(e)))?; 102 | assert!(resp.has("Content-Length")); 103 | let len: usize = resp 104 | .header("Content-Length") 105 | .unwrap() 106 | .parse() 107 | .unwrap_or_default(); 108 | trace!("Model length: {}", len); 109 | let mut bytes: Vec = Vec::with_capacity(len); 110 | resp.into_reader() 111 | .read_to_end(&mut bytes) 112 | .map_err(ModelError::IoError)?; 113 | assert_eq!(bytes.len(), len); 114 | info!("Downloaded model: {}", model); 115 | let params: WhisperContextParameters = WhisperContextParameters::default(); 116 | 117 | Ok({ 118 | Self { 119 | context: WhisperContext::new_from_buffer_with_params(&bytes, params) 120 | .map_err(ModelError::WhisperError)?, 121 | } 122 | }) 123 | } 124 | 125 | /// Transcribes audio to text, given the audio is a byte array of a file. 126 | /// Supported codecs: MP3 (Symphonia), WAV (Hound), OGG Vorbis (lewton), 127 | /// FLAC (claxon). 128 | /// 129 | /// # Arguments 130 | /// - `audio`: Audio to transcribe. An array of bytes. 131 | /// - `translate`: Whether to translate the text. 132 | /// - `word_timestamps`: Whether to output word timestamps. 133 | /// - `initial_prompt`: Optinal initial prompt to whisper model. 134 | /// - `language`: Optinal language setting for whisper model. 135 | /// - `threads`: Number of threads to use. `None` will use the number of cores from 136 | /// the `num_cpus` crate. 137 | /// # Errors 138 | /// - [`ModelError`] 139 | /// # Returns 140 | /// [Transcript] 141 | pub fn transcribe_audio( 142 | &self, 143 | audio: impl AsRef<[u8]>, 144 | translate: bool, 145 | word_timestamps: bool, 146 | initial_prompt: Option<&str>, 147 | language: Option<&str>, 148 | threads: Option, 149 | ) -> Result { 150 | trace!("Decoding audio."); 151 | let samples = transcode::decode(audio.as_ref().to_vec())?; 152 | trace!("Transcribing audio."); 153 | self.transcribe_pcm_s16le( 154 | &samples, 155 | translate, 156 | word_timestamps, 157 | initial_prompt, 158 | language, 159 | threads, 160 | ) 161 | } 162 | 163 | /// Transcribes audio to text, given the audio is an [f32] float array of codec 164 | /// `pcm_s16le` and in single-channel format. 165 | /// 166 | /// You probably want to use [`Model::transcribe_audio`] instead, unless you've already 167 | /// converted it into the correct format. 168 | /// 169 | /// # Arguments 170 | /// - `audio`: Audio to transcribe. Must be a [f32] array. 171 | /// - `translate`: Whether to translate the text. 172 | /// - `word_timestamps`: Whether to output word timestamps. 173 | /// - `initial_prompt`: Optinal initial prompt to whisper model. 174 | /// - `language`: Optinal language setting for whisper model. 175 | /// - `threads`: Number of threads to use. `None` will use the number of cores from 176 | /// 177 | /// # Errors 178 | /// - [`ModelError`] 179 | /// # Panics 180 | /// This function shouldn't panic, but may due to the underlying -sys c bindings. 181 | /// # Returns 182 | /// [Transcript] 183 | pub fn transcribe_pcm_s16le( 184 | &self, 185 | audio: &[f32], 186 | translate: bool, 187 | word_timestamps: bool, 188 | initial_prompt: Option<&str>, 189 | language: Option<&str>, 190 | threads: Option, 191 | ) -> Result { 192 | trace!( 193 | "Transcribing audio: {} with translate: {translate} and timestamps: {word_timestamps}", 194 | audio.len() 195 | ); 196 | 197 | let mut params = FullParams::new(SamplingStrategy::BeamSearch { 198 | beam_size: 5, 199 | patience: 1.0, 200 | }); 201 | 202 | if let Some(prompt) = initial_prompt { 203 | params.set_initial_prompt(prompt); 204 | } 205 | 206 | params.set_language(language); 207 | 208 | params.set_translate(translate); 209 | params.set_print_special(false); 210 | params.set_print_progress(false); 211 | params.set_print_realtime(false); 212 | params.set_print_timestamps(false); 213 | params.set_token_timestamps(word_timestamps); 214 | params.set_split_on_word(true); 215 | 216 | #[allow(clippy::cast_possible_wrap, clippy::cast_possible_truncation)] 217 | let threads = threads.map_or_else(|| num_cpus::get() as i32, i32::from); 218 | 219 | trace!("Using {} threads", threads); 220 | 221 | params.set_n_threads(threads); 222 | 223 | let st = Instant::now(); 224 | let mut state = self.context.create_state().expect("failed to create state"); 225 | trace!("Transcribing audio with WhisperState"); 226 | state.full(params, audio).expect("failed to transcribe"); 227 | 228 | let num_segments = state.full_n_segments().expect("failed to get segments"); 229 | trace!("Number of segments: {}", num_segments); 230 | 231 | let mut words = Vec::new(); 232 | let mut utterances = Vec::new(); 233 | for segment_idx in 0..num_segments { 234 | let text = state 235 | .full_get_segment_text(segment_idx) 236 | .map_err(ModelError::WhisperError)?; 237 | let start = state 238 | .full_get_segment_t0(segment_idx) 239 | .map_err(ModelError::WhisperError)?; 240 | let stop = state 241 | .full_get_segment_t1(segment_idx) 242 | .map_err(ModelError::WhisperError)?; 243 | 244 | utterances.push(Utterance { start, stop, text }); 245 | 246 | if !word_timestamps { 247 | trace!("Skipping word timestamps"); 248 | continue; 249 | } 250 | 251 | trace!("Getting word timestamps for segment {}", segment_idx); 252 | 253 | let num_tokens = state 254 | .full_n_tokens(segment_idx) 255 | .map_err(ModelError::WhisperError)?; 256 | 257 | for t in 0..num_tokens { 258 | let text = state 259 | .full_get_token_text(segment_idx, t) 260 | .map_err(ModelError::WhisperError)?; 261 | let token_data = state 262 | .full_get_token_data(segment_idx, t) 263 | .map_err(ModelError::WhisperError)?; 264 | 265 | if text.starts_with("[_") { 266 | continue; 267 | } 268 | 269 | words.push(Utterance { 270 | text, 271 | start: token_data.t0, 272 | stop: token_data.t1, 273 | }); 274 | } 275 | } 276 | 277 | Ok(Transcript { 278 | utterances, 279 | processing_time: Instant::now().duration_since(st), 280 | word_utterances: if word_timestamps { Some(words) } else { None }, 281 | }) 282 | } 283 | } 284 | /// Crate error that contains an enum of all possible errors related to the model. 285 | #[derive(Debug)] 286 | pub enum ModelError { 287 | /// [`WhisperError`]. Error either loading model, or during transcription, in the 288 | /// actual whisper.cpp library 289 | WhisperError(WhisperError), 290 | /// [`ureq::Error`]. Error downloading model. 291 | DownloadError(Box), 292 | /// [`std::io::Error`]. Error reading model. 293 | IoError(std::io::Error), 294 | /// [`AudioDecodeError`]. Error decoding audio. 295 | AudioDecodeError, 296 | } 297 | 298 | #[derive(Debug, EnumIter)] 299 | pub enum ModelType { 300 | /// Tiny Whisper model - finetuned for English. 301 | /// Size: 75 MB. 302 | TinyEn, 303 | /// Tiny Whisper model. 304 | /// Size: 75 MB. 305 | Tiny, 306 | 307 | /// Base Whisper model - finetuned for English. 308 | /// Size: 142 MB. 309 | BaseEn, 310 | 311 | /// Base Whisper model. 312 | /// Size: 142 MB. 313 | Base, 314 | 315 | /// Small Whisper model - finetuned for English. 316 | /// Size: 466 MB. 317 | SmallEn, 318 | 319 | /// Small Whisper model. 320 | /// Size: 466 MB. 321 | Small, 322 | 323 | /// Medium Whisper model - finetuned for English. 324 | /// Size: 1.5 GB. 325 | MediumEn, 326 | 327 | /// Medium Whisper model. 328 | /// Size: 1.5 GB. 329 | Medium, 330 | 331 | /// Large Whisper model - old version. 332 | /// Size: 2.9 GB. 333 | LargeV1, 334 | 335 | /// Large Whisper model - V2. 336 | /// Size: 2.9 GB. 337 | LargeV2, 338 | 339 | /// Large Whisper model - V3. 340 | /// Size: 2.9 GB. 341 | LargeV3, 342 | } 343 | 344 | impl Display for ModelType { 345 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 346 | write!( 347 | f, 348 | "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-" 349 | )?; 350 | match self { 351 | Self::TinyEn => write!(f, "tiny.en.bin"), 352 | Self::Tiny => write!(f, "tiny.bin"), 353 | Self::BaseEn => write!(f, "base.en.bin"), 354 | Self::Base => write!(f, "base.bin"), 355 | Self::SmallEn => write!(f, "small.en.bin"), 356 | Self::Small => write!(f, "small.bin"), 357 | Self::MediumEn => write!(f, "medium.en.bin"), 358 | Self::Medium => write!(f, "medium.bin"), 359 | Self::LargeV1 => write!(f, "large-v1.bin"), 360 | Self::LargeV2 => write!(f, "large-v2.bin"), 361 | Self::LargeV3 => write!(f, "large-v3.bin"), 362 | } 363 | } 364 | } 365 | -------------------------------------------------------------------------------- /src/tests.rs: -------------------------------------------------------------------------------- 1 | // ModelType tests 2 | #[cfg(test)] 3 | use { 4 | crate::{Model, ModelType}, 5 | audrey::hound::WavReader, 6 | std::io::Cursor, 7 | strum::IntoEnumIterator, 8 | }; 9 | 10 | #[test] 11 | fn test_model_urls() { 12 | for model in ModelType::iter() { 13 | let url = model.to_string(); 14 | println!("Testing model: {url}"); 15 | let head = ureq::head(&url) 16 | .call() 17 | .expect("Failed to send Head request"); 18 | assert!(head.status() == 200); 19 | assert!(head.header("Content-Length").is_some()); 20 | let len: usize = head 21 | .header("Content-Length") 22 | .unwrap() 23 | .parse() 24 | .unwrap_or_default(); 25 | // Larger than the smallest model. Basiclally just check huggingface has resolved 26 | // the download URL correctly 27 | assert!(len > 77_600_000); 28 | } 29 | } 30 | 31 | #[test] 32 | fn test_transcribe() { 33 | let model = Model::download(&ModelType::TinyEn).unwrap(); 34 | let jfk_wav = include_bytes!("../samples/jfk.wav"); 35 | 36 | let mut reader = WavReader::new(Cursor::new(jfk_wav)).unwrap(); 37 | let samples: Result, _> = reader.samples().collect(); 38 | let samples = samples.unwrap(); 39 | let mut output = vec![0.0f32; samples.len()]; 40 | let _audio = whisper_rs::convert_integer_to_float_audio(&samples, &mut output).unwrap(); 41 | 42 | let transcription = model 43 | .transcribe_pcm_s16le(&output, false, false, None) 44 | .unwrap(); 45 | assert!(transcription.as_text().contains("country")); 46 | } 47 | 48 | #[test] 49 | fn test_transcribe_with_transcode() { 50 | let model = Model::download(&ModelType::TinyEn).unwrap(); 51 | let kliks_mp3 = include_bytes!("../samples/3kliks-cut.mp3"); 52 | 53 | let transcription = model 54 | .transcribe_audio(kliks_mp3, false, false, None) 55 | .unwrap(); 56 | assert!(transcription.as_text().contains("Valve")); 57 | } 58 | -------------------------------------------------------------------------------- /src/transcode.rs: -------------------------------------------------------------------------------- 1 | use rodio::{source::UniformSourceIterator, Decoder, Source}; 2 | use std::io::Cursor; 3 | 4 | use crate::ModelError; 5 | 6 | /// Decode a byte array of audio into a float array 7 | pub fn decode(bytes: Vec) -> Result, ModelError> { 8 | let input = Cursor::new(bytes); 9 | let source = Decoder::new(input).unwrap(); 10 | let output_sample_rate = 16000; 11 | let channels = 1; 12 | // Resample to output sample rate and channels 13 | let resample = UniformSourceIterator::new(source, channels, output_sample_rate); 14 | // High and low pass filters to enhance the audio 15 | let pass_filter = resample.low_pass(3000).high_pass(200).convert_samples(); 16 | let samples: Vec = pass_filter.collect::>(); 17 | let mut output: Vec = vec![0.0f32; samples.len()]; 18 | let result: Result<(), whisper_rs::WhisperError> = 19 | whisper_rs::convert_integer_to_float_audio(&samples, &mut output); 20 | result.map(|()| output).map_err(ModelError::WhisperError) 21 | } 22 | -------------------------------------------------------------------------------- /src/transcript.rs: -------------------------------------------------------------------------------- 1 | use num::integer::div_floor; 2 | use serde::{Deserialize, Serialize}; 3 | use std::time::Duration; 4 | 5 | pub use crate::Model; 6 | 7 | // Repurposed from https://github.com/m1guelpf/whisper-cli-rs/. Fixed numerous bugs/typos 8 | 9 | /// Transcript of an audio. 10 | #[derive(Debug, Serialize, Deserialize)] 11 | pub struct Transcript { 12 | /// Duration that it took to transcribe the audio. 13 | pub processing_time: Duration, 14 | /// List of utterances in the transcript - split by normal segments. 15 | pub utterances: Vec, 16 | /// List of words in the transcript - split by each word. 17 | /// Only present if `word_timestamps` is `true` in [`Model::transcribe_audio`]. 18 | pub word_utterances: Option>, 19 | } 20 | 21 | /// A single utterance in the transcript. 22 | /// Contains a start and stop timestamp. 23 | /// Also contains the text of the utterance. 24 | #[derive(Debug, Serialize, Deserialize)] 25 | pub struct Utterance { 26 | /// Timestamp of the start of the utterance, in ms 27 | pub start: i64, 28 | /// Timestamp of the end of the utterance, in ms 29 | pub stop: i64, 30 | /// Text of the utterance. 31 | pub text: String, 32 | } 33 | 34 | impl Transcript { 35 | /// Returns the transcript as a string. 36 | #[must_use] 37 | pub fn as_text(&self) -> String { 38 | self.utterances 39 | .iter() 40 | .fold(String::new(), |transcript, fragment| { 41 | transcript + format!("{}\n", fragment.text.trim()).as_str() 42 | }) 43 | } 44 | 45 | /// Returns the transcript in VTT format. 46 | #[must_use] 47 | pub fn as_vtt(&self) -> String { 48 | let vtt = self 49 | .utterances 50 | .iter() 51 | .fold(String::new(), |transcript, fragment| { 52 | transcript 53 | + format!( 54 | "{} --> {}\n{}\n\n", 55 | format_timestamp(fragment.start, true, "."), 56 | format_timestamp(fragment.stop, true, "."), 57 | fragment.text.trim().replace("-->", "->") 58 | ) 59 | .as_str() 60 | }); 61 | format!("WEBVTT\n{vtt}") 62 | } 63 | 64 | /// Returns the transcript in SRT format. 65 | #[must_use] 66 | pub fn as_srt(&self) -> String { 67 | self.utterances 68 | .iter() 69 | .fold((1, String::new()), |(i, transcript), fragment| { 70 | ( 71 | i + 1, 72 | transcript 73 | + format!( 74 | "{i}\n{} --> {}\n{}\n", 75 | format_timestamp(fragment.start, true, ","), 76 | format_timestamp(fragment.stop, true, ","), 77 | fragment.text.trim().replace("-->", "->") 78 | ) 79 | .as_str(), 80 | ) 81 | }) 82 | .1 83 | } 84 | } 85 | 86 | /// Timestamp is oddly given in number of seconds * 100, or number of milliseconds / 10. 87 | /// This function corrects it and formats it in the desired format. 88 | fn format_timestamp(num: i64, always_include_hours: bool, decimal_marker: &str) -> String { 89 | assert!(num >= 0, "non-negative timestamp expected"); 90 | let mut milliseconds: i64 = num * 10; 91 | 92 | let hours = div_floor(milliseconds, 3_600_000); 93 | milliseconds -= hours * 3_600_000; 94 | 95 | let minutes = div_floor(milliseconds, 60_000); 96 | milliseconds -= minutes * 60_000; 97 | 98 | let seconds = div_floor(milliseconds, 1_000); 99 | milliseconds -= seconds * 1_000; 100 | 101 | let hours_marker = if always_include_hours || hours != 0 { 102 | format!("{hours:02}:") 103 | } else { 104 | String::new() 105 | }; 106 | 107 | format!("{hours_marker}{minutes:02}:{seconds:02}{decimal_marker}{milliseconds:03}") 108 | } 109 | 110 | #[test] 111 | fn test_format_timestamp() { 112 | let result = format_timestamp(100, true, "."); 113 | assert_eq!(result, "00:00:01.000"); 114 | } 115 | 116 | #[test] 117 | fn test_format_timestamp_hours() { 118 | let result = format_timestamp(100, true, ","); 119 | assert_eq!(result, "00:00:01,000"); 120 | } 121 | 122 | #[test] 123 | fn test_format_timestamp_seconds() { 124 | let result = format_timestamp(100, false, "."); 125 | assert_eq!(result, "00:01.000"); 126 | } 127 | --------------------------------------------------------------------------------