osc-data 0.2.2__tar.gz → 0.2.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {osc_data-0.2.2 → osc_data-0.2.5}/.gitignore +1 -1
- {osc_data-0.2.2 → osc_data-0.2.5}/Cargo.lock +101 -37
- {osc_data-0.2.2 → osc_data-0.2.5}/Cargo.toml +4 -0
- {osc_data-0.2.2 → osc_data-0.2.5}/PKG-INFO +5 -1
- osc_data-0.2.5/osc_data/assets/audio/example.wav +0 -0
- osc_data-0.2.5/osc_data/audio.py +68 -0
- {osc_data-0.2.2 → osc_data-0.2.5}/osc_data/text.py +14 -0
- osc_data-0.2.5/osc_data/video.py +97 -0
- {osc_data-0.2.2 → osc_data-0.2.5}/pyproject.toml +6 -2
- {osc_data-0.2.2 → osc_data-0.2.5}/src/lib.rs +2 -0
- osc_data-0.2.5/src/text.rs +40 -0
- {osc_data-0.2.2 → osc_data-0.2.5}/src/text_stream.rs +3 -3
- osc_data-0.2.5/test.mp4 +0 -0
- osc_data-0.2.2/osc_data/audio.py +0 -23
- {osc_data-0.2.2 → osc_data-0.2.5}/.github/workflows/CI.yaml +0 -0
- {osc_data-0.2.2 → osc_data-0.2.5}/.python-version +0 -0
- {osc_data-0.2.2 → osc_data-0.2.5}/README.md +0 -0
- {osc_data-0.2.2 → osc_data-0.2.5}/osc_data/__init__.py +0 -0
- {osc_data-0.2.2 → osc_data-0.2.5}/osc_data/assets/text/tn/tagger.fst +0 -0
- {osc_data-0.2.2 → osc_data-0.2.5}/osc_data/assets/text/tn/verbalizer.fst +0 -0
- {osc_data-0.2.2 → osc_data-0.2.5}/osc_data/assets/text/tn/verbalizer_remove_erhua.fst +0 -0
- {osc_data-0.2.2 → osc_data-0.2.5}/osc_data/text_stream.py +0 -0
- {osc_data-0.2.2 → osc_data-0.2.5}/src/audio.rs +0 -0
- {osc_data-0.2.2 → osc_data-0.2.5}/tests/__init__.py +0 -0
- {osc_data-0.2.2 → osc_data-0.2.5}/tests/test_compute_decibel.py +0 -0
- {osc_data-0.2.2 → osc_data-0.2.5}/tests/test_low_frame_rate.py +0 -0
|
@@ -11,11 +11,17 @@ dependencies = [
|
|
|
11
11
|
"memchr",
|
|
12
12
|
]
|
|
13
13
|
|
|
14
|
+
[[package]]
|
|
15
|
+
name = "anyhow"
|
|
16
|
+
version = "1.0.99"
|
|
17
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
18
|
+
checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
|
|
19
|
+
|
|
14
20
|
[[package]]
|
|
15
21
|
name = "autocfg"
|
|
16
|
-
version = "1.
|
|
22
|
+
version = "1.5.0"
|
|
17
23
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
18
|
-
checksum = "
|
|
24
|
+
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
|
19
25
|
|
|
20
26
|
[[package]]
|
|
21
27
|
name = "cblas-sys"
|
|
@@ -71,18 +77,24 @@ checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd"
|
|
|
71
77
|
|
|
72
78
|
[[package]]
|
|
73
79
|
name = "inventory"
|
|
74
|
-
version = "0.3.
|
|
80
|
+
version = "0.3.21"
|
|
75
81
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
76
|
-
checksum = "
|
|
82
|
+
checksum = "bc61209c082fbeb19919bee74b176221b27223e27b65d781eb91af24eb1fb46e"
|
|
77
83
|
dependencies = [
|
|
78
84
|
"rustversion",
|
|
79
85
|
]
|
|
80
86
|
|
|
87
|
+
[[package]]
|
|
88
|
+
name = "itoa"
|
|
89
|
+
version = "1.0.15"
|
|
90
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
91
|
+
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
|
92
|
+
|
|
81
93
|
[[package]]
|
|
82
94
|
name = "libc"
|
|
83
|
-
version = "0.2.
|
|
95
|
+
version = "0.2.175"
|
|
84
96
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
85
|
-
checksum = "
|
|
97
|
+
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
|
|
86
98
|
|
|
87
99
|
[[package]]
|
|
88
100
|
name = "matrixmultiply"
|
|
@@ -180,17 +192,20 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
|
|
180
192
|
name = "osc-data"
|
|
181
193
|
version = "0.1.0"
|
|
182
194
|
dependencies = [
|
|
195
|
+
"anyhow",
|
|
183
196
|
"ndarray",
|
|
184
197
|
"numpy",
|
|
185
198
|
"pyo3",
|
|
186
199
|
"regex",
|
|
200
|
+
"serde",
|
|
201
|
+
"serde_json",
|
|
187
202
|
]
|
|
188
203
|
|
|
189
204
|
[[package]]
|
|
190
205
|
name = "portable-atomic"
|
|
191
|
-
version = "1.11.
|
|
206
|
+
version = "1.11.1"
|
|
192
207
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
193
|
-
checksum = "
|
|
208
|
+
checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
|
|
194
209
|
|
|
195
210
|
[[package]]
|
|
196
211
|
name = "portable-atomic-util"
|
|
@@ -203,18 +218,18 @@ dependencies = [
|
|
|
203
218
|
|
|
204
219
|
[[package]]
|
|
205
220
|
name = "proc-macro2"
|
|
206
|
-
version = "1.0.
|
|
221
|
+
version = "1.0.101"
|
|
207
222
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
208
|
-
checksum = "
|
|
223
|
+
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
|
|
209
224
|
dependencies = [
|
|
210
225
|
"unicode-ident",
|
|
211
226
|
]
|
|
212
227
|
|
|
213
228
|
[[package]]
|
|
214
229
|
name = "pyo3"
|
|
215
|
-
version = "0.25.
|
|
230
|
+
version = "0.25.1"
|
|
216
231
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
217
|
-
checksum = "
|
|
232
|
+
checksum = "8970a78afe0628a3e3430376fc5fd76b6b45c4d43360ffd6cdd40bdde72b682a"
|
|
218
233
|
dependencies = [
|
|
219
234
|
"indoc",
|
|
220
235
|
"inventory",
|
|
@@ -230,9 +245,9 @@ dependencies = [
|
|
|
230
245
|
|
|
231
246
|
[[package]]
|
|
232
247
|
name = "pyo3-build-config"
|
|
233
|
-
version = "0.25.
|
|
248
|
+
version = "0.25.1"
|
|
234
249
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
235
|
-
checksum = "
|
|
250
|
+
checksum = "458eb0c55e7ece017adeba38f2248ff3ac615e53660d7c71a238d7d2a01c7598"
|
|
236
251
|
dependencies = [
|
|
237
252
|
"once_cell",
|
|
238
253
|
"target-lexicon",
|
|
@@ -240,9 +255,9 @@ dependencies = [
|
|
|
240
255
|
|
|
241
256
|
[[package]]
|
|
242
257
|
name = "pyo3-ffi"
|
|
243
|
-
version = "0.25.
|
|
258
|
+
version = "0.25.1"
|
|
244
259
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
245
|
-
checksum = "
|
|
260
|
+
checksum = "7114fe5457c61b276ab77c5055f206295b812608083644a5c5b2640c3102565c"
|
|
246
261
|
dependencies = [
|
|
247
262
|
"libc",
|
|
248
263
|
"pyo3-build-config",
|
|
@@ -250,9 +265,9 @@ dependencies = [
|
|
|
250
265
|
|
|
251
266
|
[[package]]
|
|
252
267
|
name = "pyo3-macros"
|
|
253
|
-
version = "0.25.
|
|
268
|
+
version = "0.25.1"
|
|
254
269
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
255
|
-
checksum = "
|
|
270
|
+
checksum = "a8725c0a622b374d6cb051d11a0983786448f7785336139c3c94f5aa6bef7e50"
|
|
256
271
|
dependencies = [
|
|
257
272
|
"proc-macro2",
|
|
258
273
|
"pyo3-macros-backend",
|
|
@@ -262,9 +277,9 @@ dependencies = [
|
|
|
262
277
|
|
|
263
278
|
[[package]]
|
|
264
279
|
name = "pyo3-macros-backend"
|
|
265
|
-
version = "0.25.
|
|
280
|
+
version = "0.25.1"
|
|
266
281
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
267
|
-
checksum = "
|
|
282
|
+
checksum = "4109984c22491085343c05b0dbc54ddc405c3cf7b4374fc533f5c3313a572ccc"
|
|
268
283
|
dependencies = [
|
|
269
284
|
"heck",
|
|
270
285
|
"proc-macro2",
|
|
@@ -290,9 +305,9 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
|
|
290
305
|
|
|
291
306
|
[[package]]
|
|
292
307
|
name = "rayon"
|
|
293
|
-
version = "1.
|
|
308
|
+
version = "1.11.0"
|
|
294
309
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
295
|
-
checksum = "
|
|
310
|
+
checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
|
|
296
311
|
dependencies = [
|
|
297
312
|
"either",
|
|
298
313
|
"rayon-core",
|
|
@@ -300,9 +315,9 @@ dependencies = [
|
|
|
300
315
|
|
|
301
316
|
[[package]]
|
|
302
317
|
name = "rayon-core"
|
|
303
|
-
version = "1.
|
|
318
|
+
version = "1.13.0"
|
|
304
319
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
305
|
-
checksum = "
|
|
320
|
+
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
|
|
306
321
|
dependencies = [
|
|
307
322
|
"crossbeam-deque",
|
|
308
323
|
"crossbeam-utils",
|
|
@@ -310,9 +325,9 @@ dependencies = [
|
|
|
310
325
|
|
|
311
326
|
[[package]]
|
|
312
327
|
name = "regex"
|
|
313
|
-
version = "1.11.
|
|
328
|
+
version = "1.11.2"
|
|
314
329
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
315
|
-
checksum = "
|
|
330
|
+
checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912"
|
|
316
331
|
dependencies = [
|
|
317
332
|
"aho-corasick",
|
|
318
333
|
"memchr",
|
|
@@ -322,9 +337,9 @@ dependencies = [
|
|
|
322
337
|
|
|
323
338
|
[[package]]
|
|
324
339
|
name = "regex-automata"
|
|
325
|
-
version = "0.4.
|
|
340
|
+
version = "0.4.10"
|
|
326
341
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
327
|
-
checksum = "
|
|
342
|
+
checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6"
|
|
328
343
|
dependencies = [
|
|
329
344
|
"aho-corasick",
|
|
330
345
|
"memchr",
|
|
@@ -333,9 +348,9 @@ dependencies = [
|
|
|
333
348
|
|
|
334
349
|
[[package]]
|
|
335
350
|
name = "regex-syntax"
|
|
336
|
-
version = "0.8.
|
|
351
|
+
version = "0.8.6"
|
|
337
352
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
338
|
-
checksum = "
|
|
353
|
+
checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001"
|
|
339
354
|
|
|
340
355
|
[[package]]
|
|
341
356
|
name = "rustc-hash"
|
|
@@ -345,15 +360,64 @@ checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
|
|
|
345
360
|
|
|
346
361
|
[[package]]
|
|
347
362
|
name = "rustversion"
|
|
363
|
+
version = "1.0.22"
|
|
364
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
365
|
+
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
|
366
|
+
|
|
367
|
+
[[package]]
|
|
368
|
+
name = "ryu"
|
|
348
369
|
version = "1.0.20"
|
|
349
370
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
350
|
-
checksum = "
|
|
371
|
+
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
|
372
|
+
|
|
373
|
+
[[package]]
|
|
374
|
+
name = "serde"
|
|
375
|
+
version = "1.0.224"
|
|
376
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
377
|
+
checksum = "6aaeb1e94f53b16384af593c71e20b095e958dab1d26939c1b70645c5cfbcc0b"
|
|
378
|
+
dependencies = [
|
|
379
|
+
"serde_core",
|
|
380
|
+
"serde_derive",
|
|
381
|
+
]
|
|
382
|
+
|
|
383
|
+
[[package]]
|
|
384
|
+
name = "serde_core"
|
|
385
|
+
version = "1.0.224"
|
|
386
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
387
|
+
checksum = "32f39390fa6346e24defbcdd3d9544ba8a19985d0af74df8501fbfe9a64341ab"
|
|
388
|
+
dependencies = [
|
|
389
|
+
"serde_derive",
|
|
390
|
+
]
|
|
391
|
+
|
|
392
|
+
[[package]]
|
|
393
|
+
name = "serde_derive"
|
|
394
|
+
version = "1.0.224"
|
|
395
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
396
|
+
checksum = "87ff78ab5e8561c9a675bfc1785cb07ae721f0ee53329a595cefd8c04c2ac4e0"
|
|
397
|
+
dependencies = [
|
|
398
|
+
"proc-macro2",
|
|
399
|
+
"quote",
|
|
400
|
+
"syn",
|
|
401
|
+
]
|
|
402
|
+
|
|
403
|
+
[[package]]
|
|
404
|
+
name = "serde_json"
|
|
405
|
+
version = "1.0.145"
|
|
406
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
407
|
+
checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
|
|
408
|
+
dependencies = [
|
|
409
|
+
"itoa",
|
|
410
|
+
"memchr",
|
|
411
|
+
"ryu",
|
|
412
|
+
"serde",
|
|
413
|
+
"serde_core",
|
|
414
|
+
]
|
|
351
415
|
|
|
352
416
|
[[package]]
|
|
353
417
|
name = "syn"
|
|
354
|
-
version = "2.0.
|
|
418
|
+
version = "2.0.106"
|
|
355
419
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
356
|
-
checksum = "
|
|
420
|
+
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
|
|
357
421
|
dependencies = [
|
|
358
422
|
"proc-macro2",
|
|
359
423
|
"quote",
|
|
@@ -362,15 +426,15 @@ dependencies = [
|
|
|
362
426
|
|
|
363
427
|
[[package]]
|
|
364
428
|
name = "target-lexicon"
|
|
365
|
-
version = "0.13.
|
|
429
|
+
version = "0.13.3"
|
|
366
430
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
367
|
-
checksum = "
|
|
431
|
+
checksum = "df7f62577c25e07834649fc3b39fafdc597c0a3527dc1c60129201ccfcbaa50c"
|
|
368
432
|
|
|
369
433
|
[[package]]
|
|
370
434
|
name = "unicode-ident"
|
|
371
|
-
version = "1.0.
|
|
435
|
+
version = "1.0.19"
|
|
372
436
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
373
|
-
checksum = "
|
|
437
|
+
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
|
|
374
438
|
|
|
375
439
|
[[package]]
|
|
376
440
|
name = "unindent"
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
name = "osc-data"
|
|
3
3
|
version = "0.1.0"
|
|
4
4
|
edition = "2021"
|
|
5
|
+
readme = "README.md"
|
|
5
6
|
|
|
6
7
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
7
8
|
[lib]
|
|
@@ -13,3 +14,6 @@ pyo3 = { version = "0.25.0", features = ["extension-module", "multiple-pymethods
|
|
|
13
14
|
ndarray = { version = "0.16.1", features = ["blas", "rayon"] }
|
|
14
15
|
numpy = "0.25.0"
|
|
15
16
|
regex = "1.11.1"
|
|
17
|
+
serde = { version = "1", features = ["derive"] }
|
|
18
|
+
serde_json = "1"
|
|
19
|
+
anyhow = "1"
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: osc-data
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.5
|
|
4
4
|
Requires-Dist: kaldifst>=1.7.14
|
|
5
5
|
Requires-Dist: pydantic>=2.11.7
|
|
6
|
+
Requires-Dist: docarray
|
|
7
|
+
Requires-Dist: requests>=2.32.5
|
|
8
|
+
Requires-Dist: librosa>=0.11.0
|
|
9
|
+
Requires-Dist: av>=10.0.0
|
|
6
10
|
Summary: data represent, processing
|
|
7
11
|
Author-email: wangmengdi <790990241@qq.com>
|
|
8
12
|
Requires-Python: >=3.9
|
|
Binary file
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
from typing import Union
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from io import BytesIO
|
|
4
|
+
import requests
|
|
5
|
+
|
|
6
|
+
from docarray import BaseDoc
|
|
7
|
+
from docarray.typing import NdArray
|
|
8
|
+
from pydantic import Field, ConfigDict
|
|
9
|
+
import librosa
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Audio(BaseDoc):
|
|
13
|
+
"""Audio object that represents an audio file.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
uri (Union[str, Path]): URL of the audio file or local path.
|
|
17
|
+
sample_rate (Optional[int], optional): Sample rate of the audio file. Defaults to None.
|
|
18
|
+
data (Optional[NdArray], optional): Data of the audio file. Defaults to None.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
model_config = ConfigDict(
|
|
22
|
+
arbitrary_types_allowed=True, validate_assignment=True, extra="ignore"
|
|
23
|
+
)
|
|
24
|
+
uri: Union[str, Path] | None = Field(
|
|
25
|
+
None, description="URL of the audio file or local path."
|
|
26
|
+
)
|
|
27
|
+
sample_rate: int | None = Field(None, description="Sample rate of the audio file.")
|
|
28
|
+
data: NdArray = Field(None, description="Data of the audio file.")
|
|
29
|
+
|
|
30
|
+
def load(self, sample_rate: int | None = None, mono: bool | None = None) -> "Audio":
|
|
31
|
+
"""Load the audio file from the URL."""
|
|
32
|
+
try:
|
|
33
|
+
if Path(self.uri).exists():
|
|
34
|
+
data, sample_rate = librosa.load(self.uri, sr=sample_rate, mono=mono)
|
|
35
|
+
else:
|
|
36
|
+
bytes_ = requests.get(self.uri).content
|
|
37
|
+
data, sample_rate = librosa.load(
|
|
38
|
+
BytesIO(bytes_), sr=sample_rate, mono=mono
|
|
39
|
+
)
|
|
40
|
+
self.data = data
|
|
41
|
+
self.sample_rate = sample_rate
|
|
42
|
+
except Exception as e:
|
|
43
|
+
raise ValueError(f"Failed to load audio from {self.uri}. {e}")
|
|
44
|
+
return self
|
|
45
|
+
|
|
46
|
+
def load_example(self) -> "Audio":
|
|
47
|
+
example_path = Path(__file__).parent / "assets" / "audio" / "example.wav"
|
|
48
|
+
self.uri = example_path
|
|
49
|
+
return self.load()
|
|
50
|
+
|
|
51
|
+
def display(self):
|
|
52
|
+
"""Display the audio file."""
|
|
53
|
+
from IPython.display import Audio as IPAudio
|
|
54
|
+
|
|
55
|
+
return IPAudio(
|
|
56
|
+
data=self.data,
|
|
57
|
+
rate=self.sample_rate,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def duration_s(self):
|
|
62
|
+
"""Get the duration of the audio file in seconds."""
|
|
63
|
+
return librosa.get_duration(y=self.data, sr=self.sample_rate)
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def duration_ms(self):
|
|
67
|
+
"""Get the duration of the audio file in milliseconds."""
|
|
68
|
+
return self.duration_s * 1000
|
|
@@ -4,6 +4,8 @@ import string
|
|
|
4
4
|
from kaldifst import TextNormalizer as KaldiTextNormalizer
|
|
5
5
|
from pydantic import BaseModel, model_validator, ConfigDict
|
|
6
6
|
|
|
7
|
+
from ._core import text as core_text
|
|
8
|
+
|
|
7
9
|
|
|
8
10
|
EOS = "<EOS>"
|
|
9
11
|
TN_ORDERS = {
|
|
@@ -167,3 +169,15 @@ class TextNormalizer(BaseModel):
|
|
|
167
169
|
text = self.reorder.reorder(text)
|
|
168
170
|
text = self.verbalizer(text)
|
|
169
171
|
return text
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
class TextCleaner(BaseModel):
|
|
175
|
+
remove_emoji: bool = False
|
|
176
|
+
to_half_width: bool = False
|
|
177
|
+
|
|
178
|
+
def clean(self, text: str) -> str:
|
|
179
|
+
if self.remove_emoji:
|
|
180
|
+
text = core_text.remove_emojis(text)
|
|
181
|
+
if self.to_half_width:
|
|
182
|
+
text = core_text.to_half_width(text)
|
|
183
|
+
return text
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import av
|
|
4
|
+
import numpy as np
|
|
5
|
+
from docarray import BaseDoc
|
|
6
|
+
from docarray.typing import VideoNdArray, VideoUrl
|
|
7
|
+
from pydantic import Field, ConfigDict
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Video(BaseDoc):
|
|
11
|
+
"""Video object that represents a video file.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
uri (Union[str, Path]): URL of the video file or local path.
|
|
15
|
+
data (NdArray): Frames data (N, H, W, 3) uint8 RGB.
|
|
16
|
+
fps (float): Frames per second.
|
|
17
|
+
duration (float): Duration in seconds.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
model_config = ConfigDict(
|
|
21
|
+
arbitrary_types_allowed=True, validate_assignment=True, extra="ignore"
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
uri: VideoUrl | None = Field(
|
|
25
|
+
None, description="URL of the video file or local path."
|
|
26
|
+
)
|
|
27
|
+
data: VideoNdArray = Field(None, description="Frames data (N, H, W, 3) uint8 RGB.")
|
|
28
|
+
key_frames: list[int] | None = Field(None, description="Key frames")
|
|
29
|
+
fps: int | None = Field(None, description="Frames per second")
|
|
30
|
+
duration: float | None = Field(None, description="Duration in seconds")
|
|
31
|
+
|
|
32
|
+
def load(self) -> "Video":
|
|
33
|
+
"""Load the video from local path or URL using av library."""
|
|
34
|
+
if self.uri is None:
|
|
35
|
+
raise ValueError("Video URI is not set")
|
|
36
|
+
|
|
37
|
+
try:
|
|
38
|
+
with av.open(str(self.uri)) as container:
|
|
39
|
+
video_stream = container.streams.video[0]
|
|
40
|
+
|
|
41
|
+
# 获取视频基本信息
|
|
42
|
+
self.fps = round(video_stream.average_rate)
|
|
43
|
+
self.duration = round(float(video_stream.duration * video_stream.time_base), 2)
|
|
44
|
+
|
|
45
|
+
# 提取所有帧和关键帧
|
|
46
|
+
frames = []
|
|
47
|
+
key_frame_indices = []
|
|
48
|
+
|
|
49
|
+
for i, frame in enumerate(container.decode(video=0)):
|
|
50
|
+
# 转换为RGB格式的numpy数组
|
|
51
|
+
frame_rgb = frame.to_ndarray(format="rgb24")
|
|
52
|
+
frames.append(frame_rgb)
|
|
53
|
+
|
|
54
|
+
# 检查是否为关键帧
|
|
55
|
+
if frame.key_frame:
|
|
56
|
+
key_frame_indices.append(i)
|
|
57
|
+
|
|
58
|
+
# 将帧数据组合成VideoNdArray格式 (N, H, W, 3)
|
|
59
|
+
if frames:
|
|
60
|
+
self.data = np.array(frames, dtype=np.uint8)
|
|
61
|
+
self.key_frames = key_frame_indices
|
|
62
|
+
else:
|
|
63
|
+
self.data = None
|
|
64
|
+
self.key_frames = []
|
|
65
|
+
|
|
66
|
+
except Exception as e:
|
|
67
|
+
# 如果加载失败,重置所有属性
|
|
68
|
+
self.data = None
|
|
69
|
+
self.key_frames = []
|
|
70
|
+
self.fps = None
|
|
71
|
+
self.duration = None
|
|
72
|
+
raise RuntimeError(f"Failed to load video: {e}")
|
|
73
|
+
|
|
74
|
+
return self
|
|
75
|
+
|
|
76
|
+
def split_by_key_frames(self) -> list[VideoNdArray]:
|
|
77
|
+
"""Split the video by key frames."""
|
|
78
|
+
if self.key_frames is None:
|
|
79
|
+
raise ValueError("Key frames are not set")
|
|
80
|
+
if len(self.key_frames) == 0 or len(self.key_frames) == 1:
|
|
81
|
+
return [self.data]
|
|
82
|
+
videos = []
|
|
83
|
+
start = 0
|
|
84
|
+
for i in self.key_frames[1:]:
|
|
85
|
+
videos.append(self.data[start:i])
|
|
86
|
+
start = i
|
|
87
|
+
videos.append(self.data[start:])
|
|
88
|
+
return videos
|
|
89
|
+
|
|
90
|
+
def display(self):
|
|
91
|
+
"""Display the video data."""
|
|
92
|
+
if hasattr(self.data, "display"):
|
|
93
|
+
self.data.display()
|
|
94
|
+
else:
|
|
95
|
+
print(
|
|
96
|
+
f"Video data shape: {self.data.shape if self.data is not None else 'None'}"
|
|
97
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "osc-data"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.5"
|
|
4
4
|
description = "data represent, processing"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -10,6 +10,10 @@ requires-python = ">=3.9"
|
|
|
10
10
|
dependencies = [
|
|
11
11
|
"kaldifst>=1.7.14",
|
|
12
12
|
"pydantic>=2.11.7",
|
|
13
|
+
"docarray",
|
|
14
|
+
"requests>=2.32.5",
|
|
15
|
+
"librosa>=0.11.0",
|
|
16
|
+
"av>=10.0.0",
|
|
13
17
|
]
|
|
14
18
|
|
|
15
19
|
[tool.maturin]
|
|
@@ -23,7 +27,7 @@ build-backend = "maturin"
|
|
|
23
27
|
[dependency-groups]
|
|
24
28
|
dev = [
|
|
25
29
|
"ipykernel>=6.29.5",
|
|
26
|
-
"maturin>=1.8.
|
|
30
|
+
"maturin>=1.8.7",
|
|
27
31
|
"numpy>=2.0.2",
|
|
28
32
|
"pip>=25.1.1",
|
|
29
33
|
]
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
mod audio;
|
|
2
|
+
mod text;
|
|
2
3
|
mod text_stream;
|
|
3
4
|
use pyo3::prelude::*;
|
|
4
5
|
|
|
@@ -7,5 +8,6 @@ use pyo3::prelude::*;
|
|
|
7
8
|
fn rust_ext<'py>(_py: Python<'py>, m: &Bound<'py, PyModule>) -> PyResult<()> {
|
|
8
9
|
let _ = audio::register_module(m)?;
|
|
9
10
|
let _ = text_stream::register_module(m)?;
|
|
11
|
+
let _ = text::register_module(m)?;
|
|
10
12
|
Ok(())
|
|
11
13
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
use pyo3::prelude::*;
|
|
2
|
+
use regex::Regex;
|
|
3
|
+
|
|
4
|
+
#[pyfunction]
|
|
5
|
+
fn remove_emojis(input: &str) -> String {
|
|
6
|
+
// 匹配常见 emoji 的 Unicode 范围
|
|
7
|
+
let emoji_regex = Regex::new(
|
|
8
|
+
r"[\u{1F600}-\u{1F64F}\
|
|
9
|
+
\u{1F300}-\u{1F5FF}\
|
|
10
|
+
\u{1F680}-\u{1F6FF}\
|
|
11
|
+
\u{1F1E6}-\u{1F1FF}\
|
|
12
|
+
\u{2600}-\u{26FF}\
|
|
13
|
+
\u{2700}-\u{27BF}]",
|
|
14
|
+
)
|
|
15
|
+
.unwrap();
|
|
16
|
+
emoji_regex.replace_all(input, "").to_string()
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
#[pyfunction]
|
|
20
|
+
fn to_half_width(input: String) -> String {
|
|
21
|
+
input
|
|
22
|
+
.chars()
|
|
23
|
+
.map(|c| match c {
|
|
24
|
+
'\u{3000}' => ' ', // 全角空格
|
|
25
|
+
'\u{FF01}'..='\u{FF5E}' => {
|
|
26
|
+
// 常见全角字符范围(!~)
|
|
27
|
+
std::char::from_u32((c as u32) - 0xFEE0).unwrap_or(c)
|
|
28
|
+
}
|
|
29
|
+
_ => c,
|
|
30
|
+
})
|
|
31
|
+
.collect()
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
pub fn register_module(core_module: &Bound<'_, PyModule>) -> PyResult<()> {
|
|
35
|
+
let text_module = PyModule::new(core_module.py(), "text")?;
|
|
36
|
+
text_module.add_function(wrap_pyfunction!(remove_emojis, &text_module)?)?;
|
|
37
|
+
text_module.add_function(wrap_pyfunction!(to_half_width, &text_module)?)?;
|
|
38
|
+
core_module.add_submodule(&text_module)?;
|
|
39
|
+
Ok(())
|
|
40
|
+
}
|
|
@@ -198,8 +198,8 @@ fn remove_emojis(input: &str) -> String {
|
|
|
198
198
|
}
|
|
199
199
|
|
|
200
200
|
pub fn register_module(core_module: &Bound<'_, PyModule>) -> PyResult<()> {
|
|
201
|
-
let
|
|
202
|
-
|
|
203
|
-
core_module.add_submodule(&
|
|
201
|
+
let text_stream_module = PyModule::new(core_module.py(), "text_stream")?;
|
|
202
|
+
text_stream_module.add_class::<TextStreamSentencizer>()?;
|
|
203
|
+
core_module.add_submodule(&text_stream_module)?;
|
|
204
204
|
Ok(())
|
|
205
205
|
}
|
osc_data-0.2.5/test.mp4
ADDED
|
Binary file
|
osc_data-0.2.2/osc_data/audio.py
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
|
|
3
|
-
from ._core import audio
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def low_frame_rate(frames: np.ndarray, m: int, n: int) -> np.ndarray:
|
|
7
|
-
"""apply low frame rate
|
|
8
|
-
Args:
|
|
9
|
-
frames: input frames. shape: (batch_size, n_frames, n_features)
|
|
10
|
-
m: number of frames to combine
|
|
11
|
-
n: number of frames to skip
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
return audio.low_frame_rate(frames, m, n)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def compute_decibel(frames: np.ndarray) -> np.ndarray:
|
|
18
|
-
"""compute decibel
|
|
19
|
-
Args:
|
|
20
|
-
frames: input frames. shape: (n_frames, n_features)
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
return audio.compute_decibel(frames)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|