videosdk-plugins-rnnoise-dev 0.0.63.dev0__py3-none-any.whl → 0.0.63.dev2__py3-none-any.whl
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.
- videosdk/plugins/rnnoise/build_rnnoise.py +11 -66
- videosdk/plugins/rnnoise/denoise.py +20 -10
- videosdk/plugins/rnnoise/files/librnnoise.0.dylib +0 -0
- videosdk/plugins/rnnoise/files/librnnoise.dylib +0 -0
- videosdk/plugins/rnnoise/rnnoise.py +10 -44
- videosdk/plugins/rnnoise/version.py +1 -1
- {videosdk_plugins_rnnoise_dev-0.0.63.dev0.dist-info → videosdk_plugins_rnnoise_dev-0.0.63.dev2.dist-info}/METADATA +3 -3
- videosdk_plugins_rnnoise_dev-0.0.63.dev2.dist-info/RECORD +11 -0
- videosdk_plugins_rnnoise_dev-0.0.63.dev0.dist-info/RECORD +0 -11
- {videosdk_plugins_rnnoise_dev-0.0.63.dev0.dist-info → videosdk_plugins_rnnoise_dev-0.0.63.dev2.dist-info}/WHEEL +0 -0
|
@@ -24,97 +24,42 @@ def run_subprocess(cmd, cwd=None):
|
|
|
24
24
|
raise
|
|
25
25
|
|
|
26
26
|
def build_rnnoise():
|
|
27
|
-
|
|
28
|
-
if os.path.exists("/.dockerenv") or os.environ.get("DOCKER_CONTAINER"):
|
|
29
|
-
os_sys = "Linux"
|
|
30
|
-
else:
|
|
31
|
-
os_sys = platform.system()
|
|
27
|
+
os_sys = platform.system()
|
|
32
28
|
repo_url = "https://github.com/xiph/rnnoise.git"
|
|
33
|
-
|
|
29
|
+
|
|
34
30
|
git_tip = "Install git (e.g., apt install git on Debian/Ubuntu, brew install git on macOS, or Chocolatey on Windows)."
|
|
35
31
|
check_command("git", git_tip)
|
|
36
|
-
|
|
32
|
+
|
|
37
33
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
38
34
|
run_subprocess(["git", "clone", repo_url, tmpdir])
|
|
39
35
|
os.chdir(tmpdir)
|
|
40
36
|
if os_sys == "Darwin" or os_sys == "Linux":
|
|
41
|
-
# Check required Unix build tools
|
|
42
37
|
unix_tip = "Install build tools (e.g., apt install build-essential autoconf automake libtool on Debian/Ubuntu; brew install autoconf automake libtool on macOS)."
|
|
43
38
|
for tool in ["autoconf", "automake", "libtool", "make"]:
|
|
44
39
|
check_command(tool, unix_tip)
|
|
45
|
-
|
|
46
|
-
# Generate build files and compile
|
|
40
|
+
|
|
47
41
|
run_subprocess(["./autogen.sh"])
|
|
48
42
|
run_subprocess(["./configure"])
|
|
49
43
|
run_subprocess(["make"])
|
|
50
44
|
lib_dir = ".libs"
|
|
51
|
-
|
|
52
|
-
# Force Linux .so file when running in Docker container
|
|
53
|
-
if os.path.exists("/.dockerenv") or os.environ.get("DOCKER_CONTAINER"):
|
|
54
|
-
lib_file = "librnnoise.so"
|
|
55
|
-
print(f"🔧 Docker detected, forcing .so file: {lib_file}")
|
|
56
|
-
else:
|
|
57
|
-
lib_file = "librnnoise.dylib" if os_sys == "Darwin" else "librnnoise.so"
|
|
58
|
-
print(f"🔧 Host system detected: {os_sys}, using: {lib_file}")
|
|
59
|
-
|
|
45
|
+
lib_file = "librnnoise.dylib" if os_sys == "Darwin" else "librnnoise.so"
|
|
60
46
|
built_lib = os.path.join(lib_dir, lib_file)
|
|
61
47
|
elif os_sys == "Windows":
|
|
62
|
-
# Check nmake for Visual Studio-based build
|
|
63
48
|
nmake_tip = "Install Visual Studio (community edition) and run this script from Developer Command Prompt. Alternatively, use MSYS2 (install via https://www.msys2.org/) and run make in the repo."
|
|
64
49
|
check_command("nmake", nmake_tip)
|
|
65
|
-
|
|
66
50
|
os.chdir("msvc")
|
|
67
|
-
# Assumes Visual Studio is installed; run from Developer Command Prompt if needed
|
|
68
51
|
run_subprocess(["nmake", "/f", "Makefile.ms"])
|
|
69
|
-
built_lib = "rnnoise.dll"
|
|
52
|
+
built_lib = "rnnoise.dll"
|
|
70
53
|
else:
|
|
71
54
|
raise ValueError(f"Unsupported OS: {os_sys}. Manual build required (clone repo and follow README).")
|
|
72
|
-
|
|
55
|
+
|
|
73
56
|
if not os.path.exists(built_lib):
|
|
74
|
-
raise FileNotFoundError(f"Build failed: {built_lib} not found. Ensure build tools are installed and environment is set up
|
|
75
|
-
|
|
57
|
+
raise FileNotFoundError(f"Build failed: {built_lib} not found. Ensure build tools are installed and environment is set up.")
|
|
58
|
+
|
|
76
59
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
|
77
60
|
target_dir = os.path.join(script_dir, "files")
|
|
78
61
|
os.makedirs(target_dir, exist_ok=True)
|
|
79
|
-
|
|
80
|
-
# Force .so files when running in Docker
|
|
81
|
-
if os.path.exists("/.dockerenv") or os.environ.get("DOCKER_CONTAINER"):
|
|
82
|
-
# Look for shared library specifically
|
|
83
|
-
shared_lib = os.path.join(lib_dir, "librnnoise.so")
|
|
84
|
-
static_lib = os.path.join(lib_dir, "librnnoise.a")
|
|
85
|
-
|
|
86
|
-
if os.path.exists(shared_lib):
|
|
87
|
-
source_lib = shared_lib
|
|
88
|
-
print(f"🔧 Found shared library: {source_lib}")
|
|
89
|
-
elif os.path.exists(static_lib):
|
|
90
|
-
# If no shared library, create one from static library
|
|
91
|
-
print(f"🔧 Creating shared library from static library")
|
|
92
|
-
# Extract object files from static library
|
|
93
|
-
run_subprocess(["ar", "-x", static_lib])
|
|
94
|
-
# Create shared library from object files
|
|
95
|
-
obj_files = [f for f in os.listdir(".") if f.endswith(".o")]
|
|
96
|
-
run_subprocess(["gcc", "-shared", "-o", shared_lib] + obj_files + ["-lm"])
|
|
97
|
-
source_lib = shared_lib
|
|
98
|
-
else:
|
|
99
|
-
raise FileNotFoundError(f"No librnnoise library found in {lib_dir}")
|
|
100
|
-
|
|
101
|
-
target_lib = os.path.join(target_dir, "librnnoise.so")
|
|
102
|
-
shutil.copy(source_lib, target_lib)
|
|
103
|
-
print(f"🔧 Copied {source_lib} to {target_lib}")
|
|
104
|
-
|
|
105
|
-
# Also create a symlink for compatibility
|
|
106
|
-
symlink_path = os.path.join(target_dir, "librnnoise.dylib")
|
|
107
|
-
if os.path.exists(symlink_path):
|
|
108
|
-
os.remove(symlink_path)
|
|
109
|
-
os.symlink("librnnoise.so", symlink_path)
|
|
110
|
-
print(f"🔧 Created symlink: librnnoise.dylib -> librnnoise.so")
|
|
111
|
-
|
|
112
|
-
# Copy to the mounted volume location
|
|
113
|
-
mounted_target = "/output/librnnoise.so"
|
|
114
|
-
shutil.copy(source_lib, mounted_target)
|
|
115
|
-
print(f"🔧 Copied to mounted volume: {mounted_target}")
|
|
116
|
-
else:
|
|
117
|
-
shutil.copy(built_lib, os.path.join(target_dir, os.path.basename(built_lib)))
|
|
62
|
+
shutil.copy(built_lib, os.path.join(target_dir, os.path.basename(built_lib)))
|
|
118
63
|
|
|
119
64
|
if __name__ == "__main__":
|
|
120
65
|
try:
|
|
@@ -123,4 +68,4 @@ if __name__ == "__main__":
|
|
|
123
68
|
except Exception as e:
|
|
124
69
|
print(f"Build failed: {e}")
|
|
125
70
|
print("If in a container/cloud/terminal, ensure tools are installed (e.g., via apt/brew/Chocolatey) or build manually per RNNoise README: https://github.com/xiph/rnnoise")
|
|
126
|
-
sys.exit(1)
|
|
71
|
+
sys.exit(1)
|
|
@@ -4,12 +4,15 @@ from .rnnoise import RNN
|
|
|
4
4
|
import numpy as np
|
|
5
5
|
import resampy
|
|
6
6
|
|
|
7
|
+
|
|
7
8
|
class RNNoise(Denoise):
|
|
8
9
|
def __init__(self):
|
|
10
|
+
"""Initialize the RNNoise denoise plugin.
|
|
11
|
+
"""
|
|
9
12
|
super().__init__()
|
|
10
13
|
self.rnnoise = RNN()
|
|
11
14
|
self._target_sample_rate = 48000
|
|
12
|
-
self._frame_duration_ms = 20
|
|
15
|
+
self._frame_duration_ms = 20
|
|
13
16
|
self._rnnoise_frame_size = 480
|
|
14
17
|
|
|
15
18
|
async def denoise(self, audio_frames: bytes, **kwargs: Any) -> bytes:
|
|
@@ -18,29 +21,35 @@ class RNNoise(Denoise):
|
|
|
18
21
|
|
|
19
22
|
audio_np = np.frombuffer(audio_frames, dtype=np.int16)
|
|
20
23
|
num_samples = len(audio_np)
|
|
21
|
-
original_sample_rate = int(
|
|
24
|
+
original_sample_rate = int(
|
|
25
|
+
num_samples * 1000 / self._frame_duration_ms)
|
|
22
26
|
|
|
23
27
|
if original_sample_rate != self._target_sample_rate:
|
|
24
28
|
audio_float = audio_np.astype(np.float32) / 32767.0
|
|
25
|
-
resampled_audio_float = resampy.resample(
|
|
26
|
-
|
|
29
|
+
resampled_audio_float = resampy.resample(
|
|
30
|
+
audio_float, sr_orig=original_sample_rate, sr_new=self._target_sample_rate)
|
|
31
|
+
resampled_audio_np = (resampled_audio_float *
|
|
32
|
+
32767.0).astype(np.int16)
|
|
27
33
|
else:
|
|
28
34
|
resampled_audio_np = audio_np
|
|
29
35
|
|
|
30
|
-
num_rnnoise_frames = len(
|
|
36
|
+
num_rnnoise_frames = len(
|
|
37
|
+
resampled_audio_np) // self._rnnoise_frame_size
|
|
31
38
|
denoised_chunks = []
|
|
32
39
|
|
|
33
40
|
for i in range(num_rnnoise_frames):
|
|
34
41
|
start = i * self._rnnoise_frame_size
|
|
35
42
|
end = start + self._rnnoise_frame_size
|
|
36
43
|
chunk = resampled_audio_np[start:end]
|
|
37
|
-
|
|
44
|
+
|
|
38
45
|
if len(chunk) != self._rnnoise_frame_size:
|
|
39
46
|
continue
|
|
40
47
|
|
|
41
48
|
chunk_bytes = chunk.tobytes()
|
|
42
|
-
_vod_prob, denoised_chunk_bytes = self.rnnoise.process_frame(
|
|
43
|
-
|
|
49
|
+
_vod_prob, denoised_chunk_bytes = self.rnnoise.process_frame(
|
|
50
|
+
chunk_bytes)
|
|
51
|
+
denoised_chunk_np = np.frombuffer(
|
|
52
|
+
denoised_chunk_bytes, dtype=np.int16)
|
|
44
53
|
denoised_chunks.append(denoised_chunk_np)
|
|
45
54
|
|
|
46
55
|
if not denoised_chunks:
|
|
@@ -50,7 +59,8 @@ class RNNoise(Denoise):
|
|
|
50
59
|
|
|
51
60
|
if original_sample_rate != self._target_sample_rate:
|
|
52
61
|
denoised_float = denoised_audio_np.astype(np.float32) / 32767.0
|
|
53
|
-
original_format_float = resampy.resample(
|
|
62
|
+
original_format_float = resampy.resample(
|
|
63
|
+
denoised_float, sr_orig=self._target_sample_rate, sr_new=original_sample_rate)
|
|
54
64
|
final_audio_np = (original_format_float * 32767.0).astype(np.int16)
|
|
55
65
|
else:
|
|
56
66
|
final_audio_np = denoised_audio_np
|
|
@@ -59,4 +69,4 @@ class RNNoise(Denoise):
|
|
|
59
69
|
|
|
60
70
|
async def aclose(self) -> None:
|
|
61
71
|
self.rnnoise.destroy()
|
|
62
|
-
await super().aclose()
|
|
72
|
+
await super().aclose()
|
|
Binary file
|
|
Binary file
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import ctypes
|
|
2
|
-
import numpy as np
|
|
3
|
-
import os
|
|
1
|
+
import ctypes,numpy,os
|
|
4
2
|
import platform
|
|
5
3
|
|
|
6
4
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
|
@@ -27,51 +25,19 @@ except OSError as e:
|
|
|
27
25
|
f"Original error: {e}"
|
|
28
26
|
) from e
|
|
29
27
|
|
|
30
|
-
|
|
31
|
-
lib.
|
|
28
|
+
lib.rnnoise_process_frame.argtypes = [ctypes.c_void_p,ctypes.POINTER(ctypes.c_float),ctypes.POINTER(ctypes.c_float)]
|
|
29
|
+
lib.rnnoise_process_frame.restype = ctypes.c_float
|
|
32
30
|
lib.rnnoise_create.restype = ctypes.c_void_p
|
|
33
31
|
lib.rnnoise_destroy.argtypes = [ctypes.c_void_p]
|
|
34
|
-
lib.rnnoise_process_frame.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float)]
|
|
35
|
-
lib.rnnoise_process_frame.restype = ctypes.c_float
|
|
36
32
|
|
|
37
33
|
class RNN(object):
|
|
38
34
|
def __init__(self):
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
# Create a copy of the input buffer to avoid modifying the original
|
|
46
|
-
if isinstance(inbuf, bytes):
|
|
47
|
-
# Convert bytes to numpy array
|
|
48
|
-
audio_data = np.frombuffer(inbuf, dtype=np.int16)
|
|
49
|
-
else:
|
|
50
|
-
audio_data = np.array(inbuf, dtype=np.int16)
|
|
51
|
-
|
|
52
|
-
# Ensure we have exactly 480 samples
|
|
53
|
-
if len(audio_data) != 480:
|
|
54
|
-
raise ValueError(f"Expected 480 samples, got {len(audio_data)}")
|
|
55
|
-
|
|
56
|
-
# Convert to float32 and normalize
|
|
57
|
-
audio_float = audio_data.astype(np.float32) / 32767.0
|
|
58
|
-
|
|
59
|
-
# Create output buffer
|
|
60
|
-
outbuf = np.zeros(480, dtype=np.float32)
|
|
61
|
-
|
|
62
|
-
# Get pointers
|
|
63
|
-
in_ptr = audio_float.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
|
|
64
|
-
out_ptr = outbuf.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
|
|
65
|
-
|
|
66
|
-
# Process the frame
|
|
67
|
-
VodProb = lib.rnnoise_process_frame(self.obj, out_ptr, in_ptr)
|
|
68
|
-
|
|
69
|
-
# Convert back to int16
|
|
70
|
-
outbuf_int16 = (outbuf * 32767.0).astype(np.int16)
|
|
71
|
-
|
|
72
|
-
return (VodProb, outbuf_int16.tobytes())
|
|
35
|
+
self.obj = lib.rnnoise_create()
|
|
36
|
+
def process_frame(self,inbuf):
|
|
37
|
+
outbuf = numpy.ndarray((480,), 'h', inbuf).astype(ctypes.c_float)
|
|
38
|
+
outbuf_ptr = outbuf.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
|
|
39
|
+
VodProb = lib.rnnoise_process_frame(self.obj,outbuf_ptr,outbuf_ptr)
|
|
40
|
+
return (VodProb,outbuf.astype(ctypes.c_short).tobytes())
|
|
73
41
|
|
|
74
42
|
def destroy(self):
|
|
75
|
-
|
|
76
|
-
lib.rnnoise_destroy(self.obj)
|
|
77
|
-
self.obj = None
|
|
43
|
+
lib.rnnoise_destroy(self.obj)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.0.63.
|
|
1
|
+
__version__ = "0.0.63.dev2"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: videosdk-plugins-rnnoise-dev
|
|
3
|
-
Version: 0.0.63.
|
|
3
|
+
Version: 0.0.63.dev2
|
|
4
4
|
Summary: VideoSDK Agent Framework plugin for RNNoise.
|
|
5
5
|
Author: videosdk
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -12,9 +12,9 @@ Classifier: Topic :: Multimedia :: Sound/Audio
|
|
|
12
12
|
Classifier: Topic :: Multimedia :: Video
|
|
13
13
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
14
14
|
Requires-Python: >=3.11
|
|
15
|
-
Requires-Dist: numpy>=1.
|
|
15
|
+
Requires-Dist: numpy>=1.27
|
|
16
16
|
Requires-Dist: resampy
|
|
17
|
-
Requires-Dist: videosdk-agents>=0.0.
|
|
17
|
+
Requires-Dist: videosdk-agents>=0.0.62
|
|
18
18
|
Description-Content-Type: text/markdown
|
|
19
19
|
|
|
20
20
|
# VideoSDK RNNoise Plugin
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
videosdk/plugins/rnnoise/__init__.py,sha256=W1ioncb06WtjaxKXUuhQMsr6JHZmNTPeUOXqnRkQiuw,51
|
|
2
|
+
videosdk/plugins/rnnoise/build_rnnoise.py,sha256=M8SUnNjxWOjEjYc0B4ag4w4wij1m3-_QjarqiGZ5l_w,3087
|
|
3
|
+
videosdk/plugins/rnnoise/denoise.py,sha256=Ait9K-rY4GLNRz2uz71O8WQaqqvBjSLVuqoOiRdbjjk,2564
|
|
4
|
+
videosdk/plugins/rnnoise/rnnoise.py,sha256=HJ5qx8ZFfM0TW_zeioOPoAOqDKcdB0BxCgh0MzS214Y,1359
|
|
5
|
+
videosdk/plugins/rnnoise/version.py,sha256=CBCVBGqf9vuz1ZgRnusrqqA5qiyraiv2Ch1ijKPJ2DI,28
|
|
6
|
+
videosdk/plugins/rnnoise/files/librnnoise.0.dylib,sha256=4nvKWEolh1ZfHeIeteAv0PA3bJEf8OH_dKAQNbsRtQ8,3659392
|
|
7
|
+
videosdk/plugins/rnnoise/files/librnnoise.dylib,sha256=4nvKWEolh1ZfHeIeteAv0PA3bJEf8OH_dKAQNbsRtQ8,3659392
|
|
8
|
+
videosdk/plugins/rnnoise/files/librnnoise.so,sha256=dpC40omPtQ5kr8Q6eiif8OkWVaz7DEpE2jhsGv76L9U,1048576
|
|
9
|
+
videosdk_plugins_rnnoise_dev-0.0.63.dev2.dist-info/METADATA,sha256=KvX-fCsYm2HDHz11JfZHNsEO8xZeZCJUfbzlP185JU4,1201
|
|
10
|
+
videosdk_plugins_rnnoise_dev-0.0.63.dev2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
11
|
+
videosdk_plugins_rnnoise_dev-0.0.63.dev2.dist-info/RECORD,,
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
videosdk/plugins/rnnoise/__init__.py,sha256=W1ioncb06WtjaxKXUuhQMsr6JHZmNTPeUOXqnRkQiuw,51
|
|
2
|
-
videosdk/plugins/rnnoise/build_rnnoise.py,sha256=zzyoYX04IzHs8TWq_cEwVAbW8www20oe8ldAtGtXPWU,6004
|
|
3
|
-
videosdk/plugins/rnnoise/denoise.py,sha256=t0Y8SjdRE2iVlrP3gfwmD_ArXwcBLBCi1V9-JryBJFI,2385
|
|
4
|
-
videosdk/plugins/rnnoise/rnnoise.py,sha256=tzANc9FmNYaalcnhYwaQGVZPKTc4xBfwDAtXkPD0Bu8,2366
|
|
5
|
-
videosdk/plugins/rnnoise/version.py,sha256=Q_1rx0vr-H8kMoyc5VNkl0Tdt8P1PyFB_NoS6uiUC9g,27
|
|
6
|
-
videosdk/plugins/rnnoise/files/librnnoise.0.dylib,sha256=dQMzNPgGtW4QRECenEZi6LKvFYTSzZlgNYivy1taNGI,1048576
|
|
7
|
-
videosdk/plugins/rnnoise/files/librnnoise.dylib,sha256=dQMzNPgGtW4QRECenEZi6LKvFYTSzZlgNYivy1taNGI,1048576
|
|
8
|
-
videosdk/plugins/rnnoise/files/librnnoise.so,sha256=dpC40omPtQ5kr8Q6eiif8OkWVaz7DEpE2jhsGv76L9U,1048576
|
|
9
|
-
videosdk_plugins_rnnoise_dev-0.0.63.dev0.dist-info/METADATA,sha256=RVFg8_MTthzbVvMZHjdbIsVIu2W32yAWuZ-C2xmhJ9o,1201
|
|
10
|
-
videosdk_plugins_rnnoise_dev-0.0.63.dev0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
11
|
-
videosdk_plugins_rnnoise_dev-0.0.63.dev0.dist-info/RECORD,,
|
|
File without changes
|