proc-tap 0.2.0__tar.gz → 0.3.1__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.
- {proc_tap-0.2.0/src/proc_tap.egg-info → proc_tap-0.3.1}/PKG-INFO +125 -22
- {proc_tap-0.2.0 → proc_tap-0.3.1}/README.md +116 -21
- {proc_tap-0.2.0 → proc_tap-0.3.1}/pyproject.toml +53 -2
- {proc_tap-0.2.0 → proc_tap-0.3.1/src/proc_tap.egg-info}/PKG-INFO +125 -22
- proc_tap-0.3.1/src/proc_tap.egg-info/SOURCES.txt +33 -0
- proc_tap-0.3.1/src/proc_tap.egg-info/entry_points.txt +2 -0
- proc_tap-0.3.1/src/proc_tap.egg-info/requires.txt +27 -0
- {proc_tap-0.2.0 → proc_tap-0.3.1}/src/proctap/__init__.py +2 -2
- proc_tap-0.3.1/src/proctap/__main__.py +199 -0
- {proc_tap-0.2.0 → proc_tap-0.3.1}/src/proctap/backends/__init__.py +9 -5
- {proc_tap-0.2.0 → proc_tap-0.3.1}/src/proctap/backends/base.py +2 -1
- proc_tap-0.3.1/src/proctap/backends/converter.py +489 -0
- proc_tap-0.3.1/src/proctap/backends/linux.py +1389 -0
- {proc_tap-0.2.0 → proc_tap-0.3.1}/src/proctap/backends/macos.py +2 -2
- proc_tap-0.3.1/src/proctap/backends/pipewire_native.py +1376 -0
- proc_tap-0.3.1/src/proctap/backends/windows.py +148 -0
- proc_tap-0.3.1/src/proctap/contrib/__init__.py +41 -0
- {proc_tap-0.2.0 → proc_tap-0.3.1}/src/proctap/contrib/discord_source.py +44 -157
- proc_tap-0.3.1/src/proctap/contrib/filters/__init__.py +54 -0
- proc_tap-0.3.1/src/proctap/contrib/filters/base.py +49 -0
- proc_tap-0.3.1/src/proctap/contrib/filters/chain.py +131 -0
- proc_tap-0.3.1/src/proctap/contrib/filters/dsp.py +205 -0
- proc_tap-0.3.1/src/proctap/contrib/filters/dynamics.py +190 -0
- proc_tap-0.3.1/src/proctap/contrib/filters/vad.py +113 -0
- proc_tap-0.3.1/src/proctap/contrib/whisper_transcribe.py +504 -0
- {proc_tap-0.2.0 → proc_tap-0.3.1}/src/proctap/core.py +78 -12
- proc_tap-0.3.1/tests/test_converter_optimizations.py +339 -0
- proc_tap-0.3.1/tests/test_pipewire_native.py +275 -0
- proc_tap-0.2.0/src/proc_tap.egg-info/SOURCES.txt +0 -20
- proc_tap-0.2.0/src/proc_tap.egg-info/requires.txt +0 -15
- proc_tap-0.2.0/src/proctap/backends/linux.py +0 -521
- proc_tap-0.2.0/src/proctap/backends/windows.py +0 -85
- proc_tap-0.2.0/src/proctap/contrib/__init__.py +0 -17
- {proc_tap-0.2.0 → proc_tap-0.3.1}/LICENSE +0 -0
- {proc_tap-0.2.0 → proc_tap-0.3.1}/setup.cfg +0 -0
- {proc_tap-0.2.0 → proc_tap-0.3.1}/setup.py +0 -0
- {proc_tap-0.2.0 → proc_tap-0.3.1}/src/proc_tap.egg-info/dependency_links.txt +0 -0
- {proc_tap-0.2.0 → proc_tap-0.3.1}/src/proc_tap.egg-info/top_level.txt +0 -0
- {proc_tap-0.2.0 → proc_tap-0.3.1}/src/proctap/_native.pyi +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: proc-tap
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Cross-platform process-level audio capture library
|
|
5
5
|
Author-email: m96-chan <y_harada@technologies.moe>
|
|
6
6
|
License: MIT
|
|
@@ -28,16 +28,24 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
28
28
|
Requires-Python: >=3.10
|
|
29
29
|
Description-Content-Type: text/markdown
|
|
30
30
|
License-File: LICENSE
|
|
31
|
+
Requires-Dist: numpy>=1.20.0
|
|
32
|
+
Requires-Dist: scipy>=1.7.0
|
|
31
33
|
Requires-Dist: pulsectl>=23.5.0; sys_platform == "linux"
|
|
32
34
|
Provides-Extra: dev
|
|
33
35
|
Requires-Dist: pytest; extra == "dev"
|
|
34
36
|
Requires-Dist: mypy; extra == "dev"
|
|
35
37
|
Requires-Dist: types-setuptools; extra == "dev"
|
|
38
|
+
Requires-Dist: types-psutil; extra == "dev"
|
|
39
|
+
Requires-Dist: scipy-stubs; extra == "dev"
|
|
36
40
|
Provides-Extra: docs
|
|
37
41
|
Requires-Dist: mkdocs-material>=9.0.0; extra == "docs"
|
|
38
42
|
Requires-Dist: mkdocstrings[python]>=0.24.0; extra == "docs"
|
|
39
43
|
Provides-Extra: linux
|
|
40
44
|
Requires-Dist: pulsectl>=23.5.0; extra == "linux"
|
|
45
|
+
Provides-Extra: contrib
|
|
46
|
+
Requires-Dist: faster-whisper>=1.0.0; extra == "contrib"
|
|
47
|
+
Provides-Extra: hq-resample
|
|
48
|
+
Requires-Dist: samplerate>=0.1.0; (python_version < "3.13" or sys_platform != "win32") and extra == "hq-resample"
|
|
41
49
|
Dynamic: license-file
|
|
42
50
|
|
|
43
51
|
<div align="center">
|
|
@@ -68,10 +76,10 @@ Ideal for VRChat, games, DAWs, browsers, and AI audio analysis pipelines.
|
|
|
68
76
|
| Platform | Status | Backend | Notes |
|
|
69
77
|
|----------|--------|---------|-------|
|
|
70
78
|
| **Windows** | ✅ **Fully Supported** | WASAPI (C++ native) | Windows 10/11 (20H1+) |
|
|
71
|
-
| **Linux** |
|
|
79
|
+
| **Linux** | ✅ **Fully Supported** | PipeWire Native / PulseAudio | Per-process isolation, auto-fallback (v0.3.0+) |
|
|
72
80
|
| **macOS** | 🧪 **Experimental** | Core Audio Process Tap | macOS 14.4+ (Sonoma) required |
|
|
73
81
|
|
|
74
|
-
<sub>\* Linux
|
|
82
|
+
<sub>\* Linux is fully supported with PipeWire/PulseAudio (v0.3.0+). macOS support is experimental (see requirements).</sub>
|
|
75
83
|
|
|
76
84
|
</div>
|
|
77
85
|
|
|
@@ -83,11 +91,11 @@ Ideal for VRChat, games, DAWs, browsers, and AI audio analysis pipelines.
|
|
|
83
91
|
(VRChat, games, browsers, Discord, DAWs, streaming tools, etc.)
|
|
84
92
|
|
|
85
93
|
- 🌍 **Cross-platform architecture**
|
|
86
|
-
→ Windows (fully supported) | Linux (
|
|
94
|
+
→ Windows (fully supported) | Linux (fully supported, v0.3.0+) | macOS (experimental, 14.4+)
|
|
87
95
|
|
|
88
96
|
- ⚡ **Platform-optimized backends**
|
|
89
97
|
→ Windows: ActivateAudioInterfaceAsync (modern WASAPI)
|
|
90
|
-
→ Linux:
|
|
98
|
+
→ Linux: PipeWire Native API / PulseAudio (fully supported, v0.3.0+)
|
|
91
99
|
→ macOS: Core Audio Process Tap API (macOS 14.4+)
|
|
92
100
|
|
|
93
101
|
- 🧵 **Low-latency, thread-safe audio engine**
|
|
@@ -121,6 +129,22 @@ pip install proc-tap
|
|
|
121
129
|
sudo dnf install pulseaudio-utils
|
|
122
130
|
```
|
|
123
131
|
|
|
132
|
+
**Optional: High-Quality Audio Resampling** (74% faster / 3.8x speedup for sample rate conversion):
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
pip install proc-tap[hq-resample]
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Performance:** With `libsamplerate`, resampling achieves **0.66ms per 10ms chunk** (vs 2.6ms with scipy-only).
|
|
139
|
+
|
|
140
|
+
**Compatibility Notes:**
|
|
141
|
+
- ✅ **Python 3.10-3.12**: Works on all platforms
|
|
142
|
+
- ✅ **Linux/macOS + Python 3.13+**: Should work (you can try it!)
|
|
143
|
+
- ⚠️ **Windows + Python 3.13+**: May fail to build (as of 2025-01)
|
|
144
|
+
- If it fails, the library automatically falls back to scipy's polyphase filtering
|
|
145
|
+
- Still provides excellent audio quality, just 74% slower for resampling
|
|
146
|
+
- You can still try installing - if it works, great! If not, no harm done.
|
|
147
|
+
|
|
124
148
|
📚 **[Read the Full Documentation](https://m96-chan.github.io/ProcTap/)** for detailed guides and API reference.
|
|
125
149
|
|
|
126
150
|
**From TestPyPI** (for testing pre-releases):
|
|
@@ -139,6 +163,58 @@ pip install -e .
|
|
|
139
163
|
|
|
140
164
|
---
|
|
141
165
|
|
|
166
|
+
## 🎬 CLI Usage (Pipe to FFmpeg)
|
|
167
|
+
|
|
168
|
+
ProcTap includes a CLI for piping audio directly to FFmpeg or other tools:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
# Pipe to FFmpeg (MP3 encoding) - Direct command
|
|
172
|
+
proctap --pid 12345 --stdout | ffmpeg -f s16le -ar 48000 -ac 2 -i pipe:0 output.mp3
|
|
173
|
+
|
|
174
|
+
# Or using python -m
|
|
175
|
+
python -m proctap --pid 12345 --stdout | ffmpeg -f s16le -ar 48000 -ac 2 -i pipe:0 output.mp3
|
|
176
|
+
|
|
177
|
+
# Using process name instead of PID
|
|
178
|
+
proctap --name "VRChat.exe" --stdout | ffmpeg -f s16le -ar 48000 -ac 2 -i pipe:0 output.mp3
|
|
179
|
+
|
|
180
|
+
# FLAC encoding (lossless)
|
|
181
|
+
proctap --pid 12345 --stdout | ffmpeg -f s16le -ar 48000 -ac 2 -i pipe:0 output.flac
|
|
182
|
+
|
|
183
|
+
# Custom sample rate and mono output
|
|
184
|
+
proctap --pid 12345 --sample-rate 44100 --channels 1 --stdout | ffmpeg -f s16le -ar 44100 -ac 1 -i pipe:0 output.wav
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**CLI Options:**
|
|
188
|
+
|
|
189
|
+
| Option | Description |
|
|
190
|
+
|--------|-------------|
|
|
191
|
+
| `--pid PID` | Process ID to capture (required if `--name` not used) |
|
|
192
|
+
| `--name NAME` | Process name to capture (e.g., `VRChat.exe` or `VRChat`) |
|
|
193
|
+
| `--stdout` | Output raw PCM to stdout for piping (required) |
|
|
194
|
+
| `--sample-rate RATE` | Sample rate in Hz (default: 48000) |
|
|
195
|
+
| `--channels {1,2}` | Number of channels: 1=mono, 2=stereo (default: 2) |
|
|
196
|
+
| `--verbose` | Enable verbose logging to stderr |
|
|
197
|
+
|
|
198
|
+
**Finding Process IDs:**
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
# Windows
|
|
202
|
+
tasklist | findstr "VRChat"
|
|
203
|
+
|
|
204
|
+
# Linux/macOS
|
|
205
|
+
ps aux | grep VRChat
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
**FFmpeg Format Arguments:**
|
|
209
|
+
|
|
210
|
+
The CLI outputs raw PCM in s16le (signed 16-bit little-endian) format by default, but can be customized via `--sample-rate` and `--channels` options. FFmpeg needs these arguments:
|
|
211
|
+
- `-f s16le`: PCM format
|
|
212
|
+
- `-ar RATE`: Sample rate (must match `--sample-rate`, default 48000)
|
|
213
|
+
- `-ac CHANNELS`: Number of channels (must match `--channels`, default 2)
|
|
214
|
+
- `-i pipe:0`: Read from stdin
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
142
218
|
## 🛠 Requirements
|
|
143
219
|
|
|
144
220
|
**Windows (Fully Supported):**
|
|
@@ -147,13 +223,21 @@ pip install -e .
|
|
|
147
223
|
- WASAPI support
|
|
148
224
|
- **No admin privileges required**
|
|
149
225
|
|
|
150
|
-
**Linux (
|
|
151
|
-
- Linux with PulseAudio or PipeWire
|
|
226
|
+
**Linux (Fully Supported - v0.3.0+):**
|
|
227
|
+
- Linux with PulseAudio or PipeWire
|
|
152
228
|
- Python 3.10+
|
|
153
|
-
-
|
|
154
|
-
-
|
|
155
|
-
-
|
|
156
|
-
-
|
|
229
|
+
- **Auto-detection:** Automatically selects best available backend
|
|
230
|
+
- **Native PipeWire API** (in development, experimental):
|
|
231
|
+
- `libpipewire-0.3-dev`: `sudo apt-get install libpipewire-0.3-dev`
|
|
232
|
+
- Target latency: ~2-5ms (when fully implemented)
|
|
233
|
+
- Auto-selected when available (may fall back to subprocess)
|
|
234
|
+
- **PipeWire subprocess:**
|
|
235
|
+
- `pw-record`: install with `sudo apt-get install pipewire-media-session`
|
|
236
|
+
- **PulseAudio fallback:**
|
|
237
|
+
- `pulsectl` library: automatically installed
|
|
238
|
+
- `parec` command: `sudo apt-get install pulseaudio-utils`
|
|
239
|
+
- ✅ **Per-process isolation** using null-sink strategy
|
|
240
|
+
- ✅ **Graceful fallback** chain: Native → PipeWire subprocess → PulseAudio
|
|
157
241
|
|
|
158
242
|
**macOS (Experimental):**
|
|
159
243
|
- macOS 14.4 (Sonoma) or later
|
|
@@ -239,15 +323,29 @@ asyncio.run(main())
|
|
|
239
323
|
|
|
240
324
|
### Audio Format
|
|
241
325
|
|
|
242
|
-
**
|
|
326
|
+
**Native Backend Format** (Windows WASAPI, hardcoded in C++):
|
|
243
327
|
|
|
244
328
|
| Parameter | Value | Description |
|
|
245
329
|
|-----------|-------|-------------|
|
|
246
|
-
| Sample Rate | **44,100 Hz** | CD quality (fixed) |
|
|
247
|
-
| Channels | **2** | Stereo (fixed) |
|
|
248
|
-
| Bit Depth | **16-bit** | PCM format (fixed) |
|
|
330
|
+
| Sample Rate | **44,100 Hz** | CD quality (fixed in C++) |
|
|
331
|
+
| Channels | **2** | Stereo (fixed in C++) |
|
|
332
|
+
| Bit Depth | **16-bit** | PCM format (fixed in C++) |
|
|
333
|
+
|
|
334
|
+
**Output Format Conversion** (v0.2.1+):
|
|
335
|
+
|
|
336
|
+
The `StreamConfig` class controls the **output format** through automatic conversion:
|
|
337
|
+
- Native format → converted to match your `StreamConfig` settings
|
|
338
|
+
- Supports sample rate conversion (e.g., 44.1kHz → 48kHz)
|
|
339
|
+
- Supports channel conversion (mono ↔ stereo)
|
|
340
|
+
- Supports bit depth conversion (8/16/24/32-bit)
|
|
341
|
+
- Zero overhead when formats match (automatic bypass)
|
|
249
342
|
|
|
250
|
-
|
|
343
|
+
Example:
|
|
344
|
+
```python
|
|
345
|
+
# Get audio as 48kHz mono 24-bit
|
|
346
|
+
config = StreamConfig(sample_rate=48000, channels=1, width=3)
|
|
347
|
+
tap = ProcTap(pid, config=config)
|
|
348
|
+
```
|
|
251
349
|
|
|
252
350
|
---
|
|
253
351
|
|
|
@@ -312,7 +410,7 @@ finally:
|
|
|
312
410
|
## 🐧 Linux Example
|
|
313
411
|
|
|
314
412
|
```python
|
|
315
|
-
from proctap import
|
|
413
|
+
from proctap import ProcessAudioCapture, StreamConfig
|
|
316
414
|
import wave
|
|
317
415
|
|
|
318
416
|
pid = 12345 # Your target process ID
|
|
@@ -330,7 +428,7 @@ def on_data(pcm, frames):
|
|
|
330
428
|
config = StreamConfig(sample_rate=44100, channels=2)
|
|
331
429
|
|
|
332
430
|
try:
|
|
333
|
-
with
|
|
431
|
+
with ProcessAudioCapture(pid, config=config, on_data=on_data):
|
|
334
432
|
print("⚠️ Make sure the process is actively playing audio!")
|
|
335
433
|
input("Recording... Press Enter to stop.\n")
|
|
336
434
|
finally:
|
|
@@ -348,7 +446,7 @@ finally:
|
|
|
348
446
|
## 🍎 macOS Example
|
|
349
447
|
|
|
350
448
|
```python
|
|
351
|
-
from proctap import
|
|
449
|
+
from proctap import ProcessAudioCapture, StreamConfig
|
|
352
450
|
import wave
|
|
353
451
|
|
|
354
452
|
pid = 12345 # Your target process ID
|
|
@@ -366,7 +464,7 @@ def on_data(pcm, frames):
|
|
|
366
464
|
config = StreamConfig(sample_rate=48000, channels=2)
|
|
367
465
|
|
|
368
466
|
try:
|
|
369
|
-
with
|
|
467
|
+
with ProcessAudioCapture(pid, config=config, on_data=on_data):
|
|
370
468
|
print("⚠️ Make sure the process is actively playing audio!")
|
|
371
469
|
print("⚠️ On first run, macOS will prompt for permission.")
|
|
372
470
|
input("Recording... Press Enter to stop.\n")
|
|
@@ -403,9 +501,14 @@ pip install -e .
|
|
|
403
501
|
- Windows SDK
|
|
404
502
|
- CMake (if you modularize the C++ code)
|
|
405
503
|
|
|
406
|
-
**Linux
|
|
504
|
+
**Linux:**
|
|
505
|
+
- No C++ compiler required (pure Python)
|
|
506
|
+
- System dependencies: `pulseaudio-utils` or `pipewire` with `libpipewire-0.3-dev`
|
|
507
|
+
|
|
508
|
+
**macOS:**
|
|
407
509
|
- No C++ compiler required (pure Python)
|
|
408
|
-
-
|
|
510
|
+
- Swift toolchain (optional, for building the Swift CLI helper)
|
|
511
|
+
- If Swift is not available, pre-built binary is included in the package
|
|
409
512
|
|
|
410
513
|
---
|
|
411
514
|
|
|
@@ -26,10 +26,10 @@ Ideal for VRChat, games, DAWs, browsers, and AI audio analysis pipelines.
|
|
|
26
26
|
| Platform | Status | Backend | Notes |
|
|
27
27
|
|----------|--------|---------|-------|
|
|
28
28
|
| **Windows** | ✅ **Fully Supported** | WASAPI (C++ native) | Windows 10/11 (20H1+) |
|
|
29
|
-
| **Linux** |
|
|
29
|
+
| **Linux** | ✅ **Fully Supported** | PipeWire Native / PulseAudio | Per-process isolation, auto-fallback (v0.3.0+) |
|
|
30
30
|
| **macOS** | 🧪 **Experimental** | Core Audio Process Tap | macOS 14.4+ (Sonoma) required |
|
|
31
31
|
|
|
32
|
-
<sub>\* Linux
|
|
32
|
+
<sub>\* Linux is fully supported with PipeWire/PulseAudio (v0.3.0+). macOS support is experimental (see requirements).</sub>
|
|
33
33
|
|
|
34
34
|
</div>
|
|
35
35
|
|
|
@@ -41,11 +41,11 @@ Ideal for VRChat, games, DAWs, browsers, and AI audio analysis pipelines.
|
|
|
41
41
|
(VRChat, games, browsers, Discord, DAWs, streaming tools, etc.)
|
|
42
42
|
|
|
43
43
|
- 🌍 **Cross-platform architecture**
|
|
44
|
-
→ Windows (fully supported) | Linux (
|
|
44
|
+
→ Windows (fully supported) | Linux (fully supported, v0.3.0+) | macOS (experimental, 14.4+)
|
|
45
45
|
|
|
46
46
|
- ⚡ **Platform-optimized backends**
|
|
47
47
|
→ Windows: ActivateAudioInterfaceAsync (modern WASAPI)
|
|
48
|
-
→ Linux:
|
|
48
|
+
→ Linux: PipeWire Native API / PulseAudio (fully supported, v0.3.0+)
|
|
49
49
|
→ macOS: Core Audio Process Tap API (macOS 14.4+)
|
|
50
50
|
|
|
51
51
|
- 🧵 **Low-latency, thread-safe audio engine**
|
|
@@ -79,6 +79,22 @@ pip install proc-tap
|
|
|
79
79
|
sudo dnf install pulseaudio-utils
|
|
80
80
|
```
|
|
81
81
|
|
|
82
|
+
**Optional: High-Quality Audio Resampling** (74% faster / 3.8x speedup for sample rate conversion):
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
pip install proc-tap[hq-resample]
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Performance:** With `libsamplerate`, resampling achieves **0.66ms per 10ms chunk** (vs 2.6ms with scipy-only).
|
|
89
|
+
|
|
90
|
+
**Compatibility Notes:**
|
|
91
|
+
- ✅ **Python 3.10-3.12**: Works on all platforms
|
|
92
|
+
- ✅ **Linux/macOS + Python 3.13+**: Should work (you can try it!)
|
|
93
|
+
- ⚠️ **Windows + Python 3.13+**: May fail to build (as of 2025-01)
|
|
94
|
+
- If it fails, the library automatically falls back to scipy's polyphase filtering
|
|
95
|
+
- Still provides excellent audio quality, just 74% slower for resampling
|
|
96
|
+
- You can still try installing - if it works, great! If not, no harm done.
|
|
97
|
+
|
|
82
98
|
📚 **[Read the Full Documentation](https://m96-chan.github.io/ProcTap/)** for detailed guides and API reference.
|
|
83
99
|
|
|
84
100
|
**From TestPyPI** (for testing pre-releases):
|
|
@@ -97,6 +113,58 @@ pip install -e .
|
|
|
97
113
|
|
|
98
114
|
---
|
|
99
115
|
|
|
116
|
+
## 🎬 CLI Usage (Pipe to FFmpeg)
|
|
117
|
+
|
|
118
|
+
ProcTap includes a CLI for piping audio directly to FFmpeg or other tools:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
# Pipe to FFmpeg (MP3 encoding) - Direct command
|
|
122
|
+
proctap --pid 12345 --stdout | ffmpeg -f s16le -ar 48000 -ac 2 -i pipe:0 output.mp3
|
|
123
|
+
|
|
124
|
+
# Or using python -m
|
|
125
|
+
python -m proctap --pid 12345 --stdout | ffmpeg -f s16le -ar 48000 -ac 2 -i pipe:0 output.mp3
|
|
126
|
+
|
|
127
|
+
# Using process name instead of PID
|
|
128
|
+
proctap --name "VRChat.exe" --stdout | ffmpeg -f s16le -ar 48000 -ac 2 -i pipe:0 output.mp3
|
|
129
|
+
|
|
130
|
+
# FLAC encoding (lossless)
|
|
131
|
+
proctap --pid 12345 --stdout | ffmpeg -f s16le -ar 48000 -ac 2 -i pipe:0 output.flac
|
|
132
|
+
|
|
133
|
+
# Custom sample rate and mono output
|
|
134
|
+
proctap --pid 12345 --sample-rate 44100 --channels 1 --stdout | ffmpeg -f s16le -ar 44100 -ac 1 -i pipe:0 output.wav
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**CLI Options:**
|
|
138
|
+
|
|
139
|
+
| Option | Description |
|
|
140
|
+
|--------|-------------|
|
|
141
|
+
| `--pid PID` | Process ID to capture (required if `--name` not used) |
|
|
142
|
+
| `--name NAME` | Process name to capture (e.g., `VRChat.exe` or `VRChat`) |
|
|
143
|
+
| `--stdout` | Output raw PCM to stdout for piping (required) |
|
|
144
|
+
| `--sample-rate RATE` | Sample rate in Hz (default: 48000) |
|
|
145
|
+
| `--channels {1,2}` | Number of channels: 1=mono, 2=stereo (default: 2) |
|
|
146
|
+
| `--verbose` | Enable verbose logging to stderr |
|
|
147
|
+
|
|
148
|
+
**Finding Process IDs:**
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
# Windows
|
|
152
|
+
tasklist | findstr "VRChat"
|
|
153
|
+
|
|
154
|
+
# Linux/macOS
|
|
155
|
+
ps aux | grep VRChat
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**FFmpeg Format Arguments:**
|
|
159
|
+
|
|
160
|
+
The CLI outputs raw PCM in s16le (signed 16-bit little-endian) format by default, but can be customized via `--sample-rate` and `--channels` options. FFmpeg needs these arguments:
|
|
161
|
+
- `-f s16le`: PCM format
|
|
162
|
+
- `-ar RATE`: Sample rate (must match `--sample-rate`, default 48000)
|
|
163
|
+
- `-ac CHANNELS`: Number of channels (must match `--channels`, default 2)
|
|
164
|
+
- `-i pipe:0`: Read from stdin
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
100
168
|
## 🛠 Requirements
|
|
101
169
|
|
|
102
170
|
**Windows (Fully Supported):**
|
|
@@ -105,13 +173,21 @@ pip install -e .
|
|
|
105
173
|
- WASAPI support
|
|
106
174
|
- **No admin privileges required**
|
|
107
175
|
|
|
108
|
-
**Linux (
|
|
109
|
-
- Linux with PulseAudio or PipeWire
|
|
176
|
+
**Linux (Fully Supported - v0.3.0+):**
|
|
177
|
+
- Linux with PulseAudio or PipeWire
|
|
110
178
|
- Python 3.10+
|
|
111
|
-
-
|
|
112
|
-
-
|
|
113
|
-
-
|
|
114
|
-
-
|
|
179
|
+
- **Auto-detection:** Automatically selects best available backend
|
|
180
|
+
- **Native PipeWire API** (in development, experimental):
|
|
181
|
+
- `libpipewire-0.3-dev`: `sudo apt-get install libpipewire-0.3-dev`
|
|
182
|
+
- Target latency: ~2-5ms (when fully implemented)
|
|
183
|
+
- Auto-selected when available (may fall back to subprocess)
|
|
184
|
+
- **PipeWire subprocess:**
|
|
185
|
+
- `pw-record`: install with `sudo apt-get install pipewire-media-session`
|
|
186
|
+
- **PulseAudio fallback:**
|
|
187
|
+
- `pulsectl` library: automatically installed
|
|
188
|
+
- `parec` command: `sudo apt-get install pulseaudio-utils`
|
|
189
|
+
- ✅ **Per-process isolation** using null-sink strategy
|
|
190
|
+
- ✅ **Graceful fallback** chain: Native → PipeWire subprocess → PulseAudio
|
|
115
191
|
|
|
116
192
|
**macOS (Experimental):**
|
|
117
193
|
- macOS 14.4 (Sonoma) or later
|
|
@@ -197,15 +273,29 @@ asyncio.run(main())
|
|
|
197
273
|
|
|
198
274
|
### Audio Format
|
|
199
275
|
|
|
200
|
-
**
|
|
276
|
+
**Native Backend Format** (Windows WASAPI, hardcoded in C++):
|
|
201
277
|
|
|
202
278
|
| Parameter | Value | Description |
|
|
203
279
|
|-----------|-------|-------------|
|
|
204
|
-
| Sample Rate | **44,100 Hz** | CD quality (fixed) |
|
|
205
|
-
| Channels | **2** | Stereo (fixed) |
|
|
206
|
-
| Bit Depth | **16-bit** | PCM format (fixed) |
|
|
280
|
+
| Sample Rate | **44,100 Hz** | CD quality (fixed in C++) |
|
|
281
|
+
| Channels | **2** | Stereo (fixed in C++) |
|
|
282
|
+
| Bit Depth | **16-bit** | PCM format (fixed in C++) |
|
|
283
|
+
|
|
284
|
+
**Output Format Conversion** (v0.2.1+):
|
|
285
|
+
|
|
286
|
+
The `StreamConfig` class controls the **output format** through automatic conversion:
|
|
287
|
+
- Native format → converted to match your `StreamConfig` settings
|
|
288
|
+
- Supports sample rate conversion (e.g., 44.1kHz → 48kHz)
|
|
289
|
+
- Supports channel conversion (mono ↔ stereo)
|
|
290
|
+
- Supports bit depth conversion (8/16/24/32-bit)
|
|
291
|
+
- Zero overhead when formats match (automatic bypass)
|
|
207
292
|
|
|
208
|
-
|
|
293
|
+
Example:
|
|
294
|
+
```python
|
|
295
|
+
# Get audio as 48kHz mono 24-bit
|
|
296
|
+
config = StreamConfig(sample_rate=48000, channels=1, width=3)
|
|
297
|
+
tap = ProcTap(pid, config=config)
|
|
298
|
+
```
|
|
209
299
|
|
|
210
300
|
---
|
|
211
301
|
|
|
@@ -270,7 +360,7 @@ finally:
|
|
|
270
360
|
## 🐧 Linux Example
|
|
271
361
|
|
|
272
362
|
```python
|
|
273
|
-
from proctap import
|
|
363
|
+
from proctap import ProcessAudioCapture, StreamConfig
|
|
274
364
|
import wave
|
|
275
365
|
|
|
276
366
|
pid = 12345 # Your target process ID
|
|
@@ -288,7 +378,7 @@ def on_data(pcm, frames):
|
|
|
288
378
|
config = StreamConfig(sample_rate=44100, channels=2)
|
|
289
379
|
|
|
290
380
|
try:
|
|
291
|
-
with
|
|
381
|
+
with ProcessAudioCapture(pid, config=config, on_data=on_data):
|
|
292
382
|
print("⚠️ Make sure the process is actively playing audio!")
|
|
293
383
|
input("Recording... Press Enter to stop.\n")
|
|
294
384
|
finally:
|
|
@@ -306,7 +396,7 @@ finally:
|
|
|
306
396
|
## 🍎 macOS Example
|
|
307
397
|
|
|
308
398
|
```python
|
|
309
|
-
from proctap import
|
|
399
|
+
from proctap import ProcessAudioCapture, StreamConfig
|
|
310
400
|
import wave
|
|
311
401
|
|
|
312
402
|
pid = 12345 # Your target process ID
|
|
@@ -324,7 +414,7 @@ def on_data(pcm, frames):
|
|
|
324
414
|
config = StreamConfig(sample_rate=48000, channels=2)
|
|
325
415
|
|
|
326
416
|
try:
|
|
327
|
-
with
|
|
417
|
+
with ProcessAudioCapture(pid, config=config, on_data=on_data):
|
|
328
418
|
print("⚠️ Make sure the process is actively playing audio!")
|
|
329
419
|
print("⚠️ On first run, macOS will prompt for permission.")
|
|
330
420
|
input("Recording... Press Enter to stop.\n")
|
|
@@ -361,9 +451,14 @@ pip install -e .
|
|
|
361
451
|
- Windows SDK
|
|
362
452
|
- CMake (if you modularize the C++ code)
|
|
363
453
|
|
|
364
|
-
**Linux
|
|
454
|
+
**Linux:**
|
|
455
|
+
- No C++ compiler required (pure Python)
|
|
456
|
+
- System dependencies: `pulseaudio-utils` or `pipewire` with `libpipewire-0.3-dev`
|
|
457
|
+
|
|
458
|
+
**macOS:**
|
|
365
459
|
- No C++ compiler required (pure Python)
|
|
366
|
-
-
|
|
460
|
+
- Swift toolchain (optional, for building the Swift CLI helper)
|
|
461
|
+
- If Swift is not available, pre-built binary is included in the package
|
|
367
462
|
|
|
368
463
|
---
|
|
369
464
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "proc-tap"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.3.1"
|
|
8
8
|
description = "Cross-platform process-level audio capture library"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -35,6 +35,8 @@ classifiers = [
|
|
|
35
35
|
|
|
36
36
|
# Platform-specific dependencies (automatically installed based on OS)
|
|
37
37
|
dependencies = [
|
|
38
|
+
"numpy>=1.20.0",
|
|
39
|
+
"scipy>=1.7.0",
|
|
38
40
|
"pulsectl>=23.5.0; sys_platform == 'linux'",
|
|
39
41
|
]
|
|
40
42
|
|
|
@@ -43,11 +45,16 @@ Homepage = "https://github.com/m96-chan/ProcTap"
|
|
|
43
45
|
Repository = "https://github.com/m96-chan/ProcTap"
|
|
44
46
|
Issues = "https://github.com/m96-chan/ProcTap/issues"
|
|
45
47
|
|
|
48
|
+
[project.scripts]
|
|
49
|
+
proctap = "proctap.__main__:main"
|
|
50
|
+
|
|
46
51
|
[project.optional-dependencies]
|
|
47
52
|
dev = [
|
|
48
53
|
"pytest",
|
|
49
54
|
"mypy",
|
|
50
|
-
"types-setuptools"
|
|
55
|
+
"types-setuptools",
|
|
56
|
+
"types-psutil",
|
|
57
|
+
"scipy-stubs",
|
|
51
58
|
]
|
|
52
59
|
docs = [
|
|
53
60
|
"mkdocs-material>=9.0.0",
|
|
@@ -56,7 +63,51 @@ docs = [
|
|
|
56
63
|
linux = [
|
|
57
64
|
"pulsectl>=23.5.0",
|
|
58
65
|
]
|
|
66
|
+
# Contrib modules with optional dependencies
|
|
67
|
+
contrib = [
|
|
68
|
+
"faster-whisper>=1.0.0",
|
|
69
|
+
]
|
|
70
|
+
# High-quality resampling using libsamplerate (optional, scipy fallback available)
|
|
71
|
+
# Note: samplerate package may fail to build on Windows with Python 3.13+ due to
|
|
72
|
+
# C compiler compatibility issues (as of 2025-01). Non-Windows platforms and
|
|
73
|
+
# Python <3.13 should work fine. If installation fails, scipy's polyphase
|
|
74
|
+
# filtering provides excellent quality as a fallback (though 30-50% slower).
|
|
75
|
+
# This is an optional optimization - the converter works well without it.
|
|
76
|
+
hq-resample = [
|
|
77
|
+
"samplerate>=0.1.0; python_version < '3.13' or sys_platform != 'win32'",
|
|
78
|
+
]
|
|
59
79
|
|
|
60
80
|
[tool.setuptools.packages.find]
|
|
61
81
|
where = ["src"]
|
|
62
82
|
include = ["proctap*"]
|
|
83
|
+
|
|
84
|
+
[tool.pytest.ini_options]
|
|
85
|
+
testpaths = ["tests"]
|
|
86
|
+
python_files = ["test_*.py"]
|
|
87
|
+
python_classes = ["Test*"]
|
|
88
|
+
python_functions = ["test_*"]
|
|
89
|
+
addopts = [
|
|
90
|
+
"-v",
|
|
91
|
+
"--tb=short",
|
|
92
|
+
]
|
|
93
|
+
|
|
94
|
+
[tool.mypy]
|
|
95
|
+
python_version = "3.10"
|
|
96
|
+
warn_return_any = true
|
|
97
|
+
warn_unused_configs = true
|
|
98
|
+
disallow_untyped_defs = false
|
|
99
|
+
ignore_missing_imports = false
|
|
100
|
+
|
|
101
|
+
# Platform-specific and optional dependencies
|
|
102
|
+
[[tool.mypy.overrides]]
|
|
103
|
+
module = [
|
|
104
|
+
"pulsectl",
|
|
105
|
+
"pulsectl.*",
|
|
106
|
+
"discord",
|
|
107
|
+
"discord.*",
|
|
108
|
+
"faster_whisper",
|
|
109
|
+
"faster_whisper.*",
|
|
110
|
+
"samplerate",
|
|
111
|
+
"samplerate.*",
|
|
112
|
+
]
|
|
113
|
+
ignore_missing_imports = true
|