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.
Files changed (26) hide show
  1. {osc_data-0.2.2 → osc_data-0.2.5}/.gitignore +1 -1
  2. {osc_data-0.2.2 → osc_data-0.2.5}/Cargo.lock +101 -37
  3. {osc_data-0.2.2 → osc_data-0.2.5}/Cargo.toml +4 -0
  4. {osc_data-0.2.2 → osc_data-0.2.5}/PKG-INFO +5 -1
  5. osc_data-0.2.5/osc_data/assets/audio/example.wav +0 -0
  6. osc_data-0.2.5/osc_data/audio.py +68 -0
  7. {osc_data-0.2.2 → osc_data-0.2.5}/osc_data/text.py +14 -0
  8. osc_data-0.2.5/osc_data/video.py +97 -0
  9. {osc_data-0.2.2 → osc_data-0.2.5}/pyproject.toml +6 -2
  10. {osc_data-0.2.2 → osc_data-0.2.5}/src/lib.rs +2 -0
  11. osc_data-0.2.5/src/text.rs +40 -0
  12. {osc_data-0.2.2 → osc_data-0.2.5}/src/text_stream.rs +3 -3
  13. osc_data-0.2.5/test.mp4 +0 -0
  14. osc_data-0.2.2/osc_data/audio.py +0 -23
  15. {osc_data-0.2.2 → osc_data-0.2.5}/.github/workflows/CI.yaml +0 -0
  16. {osc_data-0.2.2 → osc_data-0.2.5}/.python-version +0 -0
  17. {osc_data-0.2.2 → osc_data-0.2.5}/README.md +0 -0
  18. {osc_data-0.2.2 → osc_data-0.2.5}/osc_data/__init__.py +0 -0
  19. {osc_data-0.2.2 → osc_data-0.2.5}/osc_data/assets/text/tn/tagger.fst +0 -0
  20. {osc_data-0.2.2 → osc_data-0.2.5}/osc_data/assets/text/tn/verbalizer.fst +0 -0
  21. {osc_data-0.2.2 → osc_data-0.2.5}/osc_data/assets/text/tn/verbalizer_remove_erhua.fst +0 -0
  22. {osc_data-0.2.2 → osc_data-0.2.5}/osc_data/text_stream.py +0 -0
  23. {osc_data-0.2.2 → osc_data-0.2.5}/src/audio.rs +0 -0
  24. {osc_data-0.2.2 → osc_data-0.2.5}/tests/__init__.py +0 -0
  25. {osc_data-0.2.2 → osc_data-0.2.5}/tests/test_compute_decibel.py +0 -0
  26. {osc_data-0.2.2 → osc_data-0.2.5}/tests/test_low_frame_rate.py +0 -0
@@ -175,5 +175,5 @@ target/
175
175
  .venv
176
176
  *.ipynb
177
177
  *.svg
178
- cargo.lock
178
+ Cargo.lock
179
179
  uv.lock
@@ -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.4.0"
22
+ version = "1.5.0"
17
23
  source = "registry+https://github.com/rust-lang/crates.io-index"
18
- checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
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.20"
80
+ version = "0.3.21"
75
81
  source = "registry+https://github.com/rust-lang/crates.io-index"
76
- checksum = "ab08d7cd2c5897f2c949e5383ea7c7db03fb19130ffcfbf7eda795137ae3cb83"
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.172"
95
+ version = "0.2.175"
84
96
  source = "registry+https://github.com/rust-lang/crates.io-index"
85
- checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
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.0"
206
+ version = "1.11.1"
192
207
  source = "registry+https://github.com/rust-lang/crates.io-index"
193
- checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e"
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.95"
221
+ version = "1.0.101"
207
222
  source = "registry+https://github.com/rust-lang/crates.io-index"
208
- checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
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.0"
230
+ version = "0.25.1"
216
231
  source = "registry+https://github.com/rust-lang/crates.io-index"
217
- checksum = "f239d656363bcee73afef85277f1b281e8ac6212a1d42aa90e55b90ed43c47a4"
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.0"
248
+ version = "0.25.1"
234
249
  source = "registry+https://github.com/rust-lang/crates.io-index"
235
- checksum = "755ea671a1c34044fa165247aaf6f419ca39caa6003aee791a0df2713d8f1b6d"
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.0"
258
+ version = "0.25.1"
244
259
  source = "registry+https://github.com/rust-lang/crates.io-index"
245
- checksum = "fc95a2e67091e44791d4ea300ff744be5293f394f1bafd9f78c080814d35956e"
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.0"
268
+ version = "0.25.1"
254
269
  source = "registry+https://github.com/rust-lang/crates.io-index"
255
- checksum = "a179641d1b93920829a62f15e87c0ed791b6c8db2271ba0fd7c2686090510214"
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.0"
280
+ version = "0.25.1"
266
281
  source = "registry+https://github.com/rust-lang/crates.io-index"
267
- checksum = "9dff85ebcaab8c441b0e3f7ae40a6963ecea8a9f5e74f647e33fcf5ec9a1e89e"
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.10.0"
308
+ version = "1.11.0"
294
309
  source = "registry+https://github.com/rust-lang/crates.io-index"
295
- checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
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.12.1"
318
+ version = "1.13.0"
304
319
  source = "registry+https://github.com/rust-lang/crates.io-index"
305
- checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
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.1"
328
+ version = "1.11.2"
314
329
  source = "registry+https://github.com/rust-lang/crates.io-index"
315
- checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
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.9"
340
+ version = "0.4.10"
326
341
  source = "registry+https://github.com/rust-lang/crates.io-index"
327
- checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
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.5"
351
+ version = "0.8.6"
337
352
  source = "registry+https://github.com/rust-lang/crates.io-index"
338
- checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
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 = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
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.101"
418
+ version = "2.0.106"
355
419
  source = "registry+https://github.com/rust-lang/crates.io-index"
356
- checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
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.2"
429
+ version = "0.13.3"
366
430
  source = "registry+https://github.com/rust-lang/crates.io-index"
367
- checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a"
431
+ checksum = "df7f62577c25e07834649fc3b39fafdc597c0a3527dc1c60129201ccfcbaa50c"
368
432
 
369
433
  [[package]]
370
434
  name = "unicode-ident"
371
- version = "1.0.18"
435
+ version = "1.0.19"
372
436
  source = "registry+https://github.com/rust-lang/crates.io-index"
373
- checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
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.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
@@ -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.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.6",
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 audio_module = PyModule::new(core_module.py(), "text_stream")?;
202
- audio_module.add_class::<TextStreamSentencizer>()?;
203
- core_module.add_submodule(&audio_module)?;
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
  }
Binary file
@@ -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