videosdk-plugins-rnnoise 0.0.22__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.

Potentially problematic release.


This version of videosdk-plugins-rnnoise might be problematic. Click here for more details.

@@ -0,0 +1,18 @@
1
+ myenv/
2
+ venv/
3
+ env/
4
+ __pycache__/
5
+
6
+ .env
7
+ .env.local
8
+ test_env/
9
+ dist/
10
+ .DS_Store
11
+
12
+ node_modules/
13
+ credentials.json
14
+ .Python
15
+ build/
16
+ eggs/
17
+ sdist/
18
+ wheels/
@@ -0,0 +1,35 @@
1
+ Metadata-Version: 2.4
2
+ Name: videosdk-plugins-rnnoise
3
+ Version: 0.0.22
4
+ Summary: VideoSDK Agent Framework plugin for RNNoise.
5
+ Author: videosdk
6
+ License-Expression: Apache-2.0
7
+ Keywords: ai,audio,lmnt,rime,tts,video,videosdk
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Topic :: Communications :: Conferencing
11
+ Classifier: Topic :: Multimedia :: Sound/Audio
12
+ Classifier: Topic :: Multimedia :: Video
13
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
14
+ Requires-Python: >=3.11
15
+ Requires-Dist: numpy>=1.26
16
+ Requires-Dist: resampy
17
+ Requires-Dist: videosdk-agents>=0.0.22
18
+ Description-Content-Type: text/markdown
19
+
20
+ # VideoSDK RNNoise Plugin
21
+
22
+ Agent Framework plugin for de-noising with RNNoise.
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ pip install videosdk-plugins-rnnoise
28
+ ```
29
+
30
+ ## Building RNNoise for your OS
31
+
32
+ To avoid OS security issues with prebuilt libraries, build RNNoise locally:
33
+ 1. Ensure you have git and build tools (autoconf/make on Mac/Linux, Visual Studio with nmake on Windows).
34
+ 2. Run `python build_rnnoise.py` in the project root.
35
+ 3. This clones RNNoise, builds the library for your OS, and places it in videosdk/plugins/rnnoise/files/.
@@ -0,0 +1,16 @@
1
+ # VideoSDK RNNoise Plugin
2
+
3
+ Agent Framework plugin for de-noising with RNNoise.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install videosdk-plugins-rnnoise
9
+ ```
10
+
11
+ ## Building RNNoise for your OS
12
+
13
+ To avoid OS security issues with prebuilt libraries, build RNNoise locally:
14
+ 1. Ensure you have git and build tools (autoconf/make on Mac/Linux, Visual Studio with nmake on Windows).
15
+ 2. Run `python build_rnnoise.py` in the project root.
16
+ 3. This clones RNNoise, builds the library for your OS, and places it in videosdk/plugins/rnnoise/files/.
@@ -0,0 +1,36 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "videosdk-plugins-rnnoise"
7
+ dynamic = ["version"]
8
+ description = "VideoSDK Agent Framework plugin for RNNoise."
9
+ readme = "README.md"
10
+ license = "Apache-2.0"
11
+ requires-python = ">=3.11"
12
+ authors = [{ name = "videosdk"}]
13
+ keywords = ["video", "audio", "ai", "lmnt", "tts", "videosdk", "rime"]
14
+ classifiers = [
15
+ "Intended Audience :: Developers",
16
+ "Development Status :: 4 - Beta",
17
+ "Intended Audience :: Developers",
18
+ "Topic :: Communications :: Conferencing",
19
+ "Topic :: Multimedia :: Sound/Audio",
20
+ "Topic :: Multimedia :: Video",
21
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
22
+ ]
23
+ dependencies = [
24
+ "videosdk-agents>=0.0.22",
25
+ "resampy",
26
+ "numpy>=1.26"
27
+ ]
28
+
29
+ [tool.hatch.version]
30
+ path = "videosdk/plugins/rnnoise/version.py"
31
+
32
+ [tool.hatch.build.targets.wheel]
33
+ packages = ["videosdk"]
34
+
35
+ [tool.hatch.build.targets.sdist]
36
+ include = ["/videosdk"]
@@ -0,0 +1,3 @@
1
+ from .denoise import RNNoise
2
+
3
+ __all__ = ["RNNoise"]
@@ -0,0 +1,76 @@
1
+ import os
2
+ import platform
3
+ import subprocess
4
+ import shutil
5
+ import tempfile
6
+
7
+ import sys
8
+ from shutil import which
9
+
10
+ def check_command(cmd, install_tip):
11
+ if not which(cmd):
12
+ raise EnvironmentError(f"{cmd} not found. Install it: {install_tip}")
13
+
14
+ def run_subprocess(cmd, cwd=None):
15
+ print(f"Running: {' '.join(cmd)}")
16
+ try:
17
+ result = subprocess.run(cmd, cwd=cwd, check=True, capture_output=True, text=True)
18
+ print(result.stdout)
19
+ if result.stderr:
20
+ print(f"Warnings/Errors: {result.stderr}")
21
+ return result
22
+ except subprocess.CalledProcessError as e:
23
+ print(f"Command failed with code {e.returncode}: {e.stderr}")
24
+ raise
25
+
26
+ def build_rnnoise():
27
+ os_sys = platform.system()
28
+ repo_url = "https://github.com/xiph/rnnoise.git"
29
+
30
+ git_tip = "Install git (e.g., apt install git on Debian/Ubuntu, brew install git on macOS, or Chocolatey on Windows)."
31
+ check_command("git", git_tip)
32
+
33
+ with tempfile.TemporaryDirectory() as tmpdir:
34
+ run_subprocess(["git", "clone", repo_url, tmpdir])
35
+ os.chdir(tmpdir)
36
+ if os_sys == "Darwin" or os_sys == "Linux":
37
+ # Check required Unix build tools
38
+ unix_tip = "Install build tools (e.g., apt install build-essential autoconf automake libtool on Debian/Ubuntu; brew install autoconf automake libtool on macOS)."
39
+ for tool in ["autoconf", "automake", "libtool", "make"]:
40
+ check_command(tool, unix_tip)
41
+
42
+ # Generate build files and compile
43
+ run_subprocess(["./autogen.sh"])
44
+ run_subprocess(["./configure"])
45
+ run_subprocess(["make"])
46
+ lib_dir = ".libs"
47
+ lib_file = "librnnoise.dylib" if os_sys == "Darwin" else "librnnoise.so"
48
+ built_lib = os.path.join(lib_dir, lib_file)
49
+ elif os_sys == "Windows":
50
+ # Check nmake for Visual Studio-based build
51
+ 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."
52
+ check_command("nmake", nmake_tip)
53
+
54
+ os.chdir("msvc")
55
+ # Assumes Visual Studio is installed; run from Developer Command Prompt if needed
56
+ run_subprocess(["nmake", "/f", "Makefile.ms"])
57
+ built_lib = "rnnoise.dll" # Adjust if name differs after build
58
+ else:
59
+ raise ValueError(f"Unsupported OS: {os_sys}. Manual build required (clone repo and follow README).")
60
+
61
+ if not os.path.exists(built_lib):
62
+ raise FileNotFoundError(f"Build failed: {built_lib} not found. Ensure build tools are installed and environment is set up (e.g., in containers, add tools via Dockerfile/package manager).")
63
+
64
+ script_dir = os.path.dirname(os.path.abspath(__file__))
65
+ target_dir = os.path.join(script_dir, "files")
66
+ os.makedirs(target_dir, exist_ok=True)
67
+ shutil.copy(built_lib, os.path.join(target_dir, os.path.basename(built_lib)))
68
+
69
+ if __name__ == "__main__":
70
+ try:
71
+ build_rnnoise()
72
+ print("RNNoise library built successfully for your OS.")
73
+ except Exception as e:
74
+ print(f"Build failed: {e}")
75
+ 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")
76
+ sys.exit(1)
@@ -0,0 +1,62 @@
1
+ from typing import Any
2
+ from videosdk.agents.denoise import Denoise
3
+ from .rnnoise import RNN
4
+ import numpy as np
5
+ import resampy
6
+
7
+ class RNNoise(Denoise):
8
+ def __init__(self):
9
+ super().__init__()
10
+ self.rnnoise = RNN()
11
+ self._target_sample_rate = 48000
12
+ self._frame_duration_ms = 20
13
+ self._rnnoise_frame_size = 480
14
+
15
+ async def denoise(self, audio_frames: bytes, **kwargs: Any) -> bytes:
16
+ if not audio_frames:
17
+ return b""
18
+
19
+ audio_np = np.frombuffer(audio_frames, dtype=np.int16)
20
+ num_samples = len(audio_np)
21
+ original_sample_rate = int(num_samples * 1000 / self._frame_duration_ms)
22
+
23
+ if original_sample_rate != self._target_sample_rate:
24
+ audio_float = audio_np.astype(np.float32) / 32767.0
25
+ resampled_audio_float = resampy.resample(audio_float, sr_orig=original_sample_rate, sr_new=self._target_sample_rate)
26
+ resampled_audio_np = (resampled_audio_float * 32767.0).astype(np.int16)
27
+ else:
28
+ resampled_audio_np = audio_np
29
+
30
+ num_rnnoise_frames = len(resampled_audio_np) // self._rnnoise_frame_size
31
+ denoised_chunks = []
32
+
33
+ for i in range(num_rnnoise_frames):
34
+ start = i * self._rnnoise_frame_size
35
+ end = start + self._rnnoise_frame_size
36
+ chunk = resampled_audio_np[start:end]
37
+
38
+ if len(chunk) != self._rnnoise_frame_size:
39
+ continue
40
+
41
+ chunk_bytes = chunk.tobytes()
42
+ _vod_prob, denoised_chunk_bytes = self.rnnoise.process_frame(chunk_bytes)
43
+ denoised_chunk_np = np.frombuffer(denoised_chunk_bytes, dtype=np.int16)
44
+ denoised_chunks.append(denoised_chunk_np)
45
+
46
+ if not denoised_chunks:
47
+ return b""
48
+
49
+ denoised_audio_np = np.concatenate(denoised_chunks)
50
+
51
+ if original_sample_rate != self._target_sample_rate:
52
+ denoised_float = denoised_audio_np.astype(np.float32) / 32767.0
53
+ original_format_float = resampy.resample(denoised_float, sr_orig=self._target_sample_rate, sr_new=original_sample_rate)
54
+ final_audio_np = (original_format_float * 32767.0).astype(np.int16)
55
+ else:
56
+ final_audio_np = denoised_audio_np
57
+
58
+ return final_audio_np.tobytes()
59
+
60
+ async def aclose(self) -> None:
61
+ self.rnnoise.destroy()
62
+ await super().aclose()
@@ -0,0 +1,43 @@
1
+ import ctypes,numpy,os
2
+ import platform
3
+
4
+ script_dir = os.path.dirname(os.path.abspath(__file__))
5
+
6
+
7
+ sys_name = platform.system()
8
+ if sys_name == "Darwin":
9
+ lib_name = "librnnoise.dylib"
10
+ elif sys_name == "Linux":
11
+ lib_name = "librnnoise.so"
12
+ elif sys_name == "Windows":
13
+ lib_name = "rnnoise.dll"
14
+ else:
15
+ raise OSError(f"Unsupported OS: {sys_name}")
16
+
17
+ lib_path = os.path.join(script_dir, "files", lib_name)
18
+
19
+ try:
20
+ lib = ctypes.cdll.LoadLibrary(lib_path)
21
+ except OSError as e:
22
+ raise OSError(
23
+ f"Error loading rnnoise library at {lib_path}. "
24
+ f"It may be corrupted or incompatible with your platform. "
25
+ f"Original error: {e}"
26
+ ) from e
27
+
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
30
+ lib.rnnoise_create.restype = ctypes.c_void_p
31
+ lib.rnnoise_destroy.argtypes = [ctypes.c_void_p]
32
+
33
+ class RNN(object):
34
+ def __init__(self):
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())
41
+
42
+ def destroy(self):
43
+ lib.rnnoise_destroy(self.obj)
@@ -0,0 +1 @@
1
+ __version__ = "0.0.22"