proc-tap 0.1.0__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.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Yusuke Harada
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,373 @@
1
+ Metadata-Version: 2.4
2
+ Name: proc-tap
3
+ Version: 0.1.0
4
+ Summary: Process-level audio tap for Windows
5
+ Requires-Python: >=3.10
6
+ Description-Content-Type: text/markdown
7
+ License-File: LICENSE
8
+ Provides-Extra: dev
9
+ Requires-Dist: pytest; extra == "dev"
10
+ Requires-Dist: mypy; extra == "dev"
11
+ Requires-Dist: types-setuptools; extra == "dev"
12
+ Dynamic: license-file
13
+
14
+ <div align="center">
15
+
16
+ # ๐Ÿ“ก ProcTap
17
+
18
+ **Per-Process Audio Capture for Windows**
19
+
20
+ [![PyPI version](https://img.shields.io/pypi/v/proc-tap?color=blue&logo=pypi&logoColor=white)](https://pypi.org/project/proc-tap/)
21
+ [![Python versions](https://img.shields.io/pypi/pyversions/proc-tap?logo=python&logoColor=white)](https://pypi.org/project/proc-tap/)
22
+ [![Downloads](https://img.shields.io/pypi/dm/proc-tap?logo=pypi&logoColor=white)](https://pypi.org/project/proc-tap/)
23
+ [![Platform](https://img.shields.io/badge/platform-Windows%2010%2F11-blue?logo=windows)](https://github.com/m96-chan/ProcTap)
24
+
25
+ [![Build wheels](https://github.com/m96-chan/ProcTap/actions/workflows/build-wheels.yml/badge.svg)](https://github.com/m96-chan/ProcTap/actions/workflows/build-wheels.yml)
26
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
27
+ [![Code style](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
28
+ [![GitHub stars](https://img.shields.io/github/stars/m96-chan/ProcTap?style=social)](https://github.com/m96-chan/ProcTap/stargazers)
29
+
30
+ ---
31
+
32
+ ProcTap is a Python library with a high-performance C++ backend that enables per-process audio capture on Windows 10/11 (20H1+) using ActivateAudioInterfaceAsync.
33
+
34
+ **Capture audio from a specific process only** โ€” without system sounds or other app audio mixed in.
35
+ Ideal for VRChat, games, DAWs, browsers, and AI audio analysis pipelines.
36
+
37
+ </div>
38
+
39
+ ---
40
+
41
+ ## ๐Ÿš€ Features
42
+
43
+ - ๐ŸŽง **Capture audio from a single target process**
44
+ (VRChat, games, browsers, Discord, DAWs, streaming tools, etc.)
45
+
46
+ - โšก **Uses ActivateAudioInterfaceAsync (modern WASAPI)**
47
+ โ†’ More stable than legacy IAudioClient2 loopback approaches
48
+
49
+ - ๐Ÿงต **Low-latency, thread-safe C++ engine**
50
+ โ†’ 44.1 kHz / stereo / 16-bit PCM format
51
+
52
+ - ๐Ÿ **Python-friendly high-level API**
53
+ - Callback-based streaming
54
+ - Async generator streaming (`async for`)
55
+
56
+ - ๐Ÿ”Œ **Native extension for high-throughput PCM delivery**
57
+
58
+ - ๐ŸชŸ **Windows-only (10/11, 20H1+)**
59
+
60
+ ---
61
+
62
+ ## ๐Ÿ“ฆ Installation
63
+
64
+ **From PyPI** (coming soon):
65
+
66
+ ```bash
67
+ pip install proctap
68
+ ```
69
+
70
+ **From TestPyPI** (for testing pre-releases):
71
+
72
+ ```bash
73
+ pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ proctap
74
+ ```
75
+
76
+ **From Source**:
77
+
78
+ ```bash
79
+ git clone https://github.com/m96-chan/ProcTap
80
+ cd ProcTap
81
+ pip install -e .
82
+ ```
83
+
84
+ ---
85
+
86
+ ## ๐Ÿ›  Requirements
87
+
88
+ - Windows 10 / 11 (20H1 or later recommended)
89
+ - Python 3.10+
90
+ - WASAPI support
91
+ - **No admin privileges required**
92
+ (Per-process loopback capture works with standard user permissions)
93
+
94
+ ---
95
+
96
+ ## ๐Ÿงฐ Basic Usage (Callback API)
97
+
98
+ ```python
99
+ from proctap import ProcTap, StreamConfig
100
+
101
+ def on_chunk(pcm: bytes, frames: int):
102
+ print(f"Received {len(pcm)} bytes ({frames} frames)")
103
+
104
+ pid = 12345 # Target process ID
105
+
106
+ tap = ProcTap(pid, StreamConfig(), on_data=on_chunk)
107
+ tap.start()
108
+
109
+ input("Recording... Press Enter to stop.\n")
110
+
111
+ tap.close()
112
+ ```
113
+
114
+ ---
115
+
116
+ ## ๐Ÿ” Async Usage (Async Generator)
117
+
118
+ ```python
119
+ import asyncio
120
+ from proctap import ProcTap
121
+
122
+ async def main():
123
+ tap = ProcTap(pid=12345)
124
+ tap.start()
125
+
126
+ async for chunk in tap.iter_chunks():
127
+ print(f"PCM chunk size: {len(chunk)} bytes")
128
+
129
+ asyncio.run(main())
130
+ ```
131
+
132
+ ---
133
+
134
+ ## ๐Ÿ“„ API Overview
135
+
136
+ ### `class ProcTap`
137
+
138
+ **Control Methods:**
139
+
140
+ | Method | Description |
141
+ |--------|-------------|
142
+ | `start()` | Start WASAPI per-process capture |
143
+ | `stop()` | Stop capture |
144
+ | `close()` | Release native resources |
145
+
146
+ **Data Access:**
147
+
148
+ | Method | Description |
149
+ |--------|-------------|
150
+ | `iter_chunks()` | Async generator yielding PCM chunks |
151
+ | `read(timeout=1.0)` | Synchronous: read one chunk (blocking) |
152
+
153
+ **Properties:**
154
+
155
+ | Property | Type | Description |
156
+ |----------|------|-------------|
157
+ | `is_running` | bool | Check if capture is active |
158
+ | `pid` | int | Get target process ID |
159
+ | `config` | StreamConfig | Get stream configuration |
160
+
161
+ **Utility Methods:**
162
+
163
+ | Method | Description |
164
+ |--------|-------------|
165
+ | `set_callback(callback)` | Change or remove audio callback |
166
+ | `get_format()` | Get audio format info (dict) |
167
+
168
+ ### Audio Format
169
+
170
+ **Note:** The native extension uses a **fixed audio format** (hardcoded in C++):
171
+
172
+ | Parameter | Value | Description |
173
+ |-----------|-------|-------------|
174
+ | Sample Rate | **44,100 Hz** | CD quality (fixed) |
175
+ | Channels | **2** | Stereo (fixed) |
176
+ | Bit Depth | **16-bit** | PCM format (fixed) |
177
+
178
+ The `StreamConfig` class exists for API compatibility but does not change the native backend format.
179
+
180
+ ---
181
+
182
+ ## ๐ŸŽฏ Use Cases
183
+
184
+ - ๐ŸŽฎ Record audio from one game only
185
+ - ๐Ÿ•ถ Capture VRChat audio cleanly (without system sounds)
186
+ - ๐ŸŽ™ Feed high-SNR audio into AI recognition models
187
+ - ๐Ÿ“น Alternative to OBS "Application Audio Capture"
188
+ - ๐ŸŽง Capture DAW/app playback for analysis tools
189
+
190
+ ---
191
+
192
+ ## ๐Ÿ“š Example: Save to WAV
193
+
194
+ ```python
195
+ from proctap import ProcTap
196
+ import wave
197
+
198
+ pid = 12345
199
+
200
+ wav = wave.open("output.wav", "wb")
201
+ wav.setnchannels(2)
202
+ wav.setsampwidth(2) # 16-bit PCM
203
+ wav.setframerate(44100) # Native format is 44.1 kHz
204
+
205
+ def on_data(pcm, frames):
206
+ wav.writeframes(pcm)
207
+
208
+ with ProcTap(pid, on_data=on_data):
209
+ input("Recording... Press Enter to stop.\n")
210
+
211
+ wav.close()
212
+ ```
213
+
214
+ ---
215
+
216
+ ## ๐Ÿ“š Example: Synchronous Read API
217
+
218
+ ```python
219
+ from proctap import ProcTap
220
+
221
+ tap = ProcTap(pid=12345)
222
+ tap.start()
223
+
224
+ try:
225
+ while True:
226
+ chunk = tap.read(timeout=1.0) # Blocking read
227
+ if chunk:
228
+ print(f"Got {len(chunk)} bytes")
229
+ # Process audio data...
230
+ else:
231
+ print("Timeout, no data")
232
+ except KeyboardInterrupt:
233
+ pass
234
+ finally:
235
+ tap.close()
236
+ ```
237
+
238
+ ---
239
+
240
+ ## ๐Ÿ— Build From Source
241
+
242
+ ```bash
243
+ git clone https://github.com/m96-chan/ProcTap
244
+ cd ProcTap
245
+ pip install -e .
246
+ ```
247
+
248
+ **Requirements:**
249
+ - Visual Studio Build Tools
250
+ - Windows SDK
251
+ - CMake (if you modularize the C++ code)
252
+
253
+ ---
254
+
255
+ ## ๐Ÿ”ง Project Structure
256
+
257
+ ```
258
+ ProcTap/
259
+ โ”œโ”€ LICENSE
260
+ โ”œโ”€ README.md
261
+ โ”œโ”€ pyproject.toml
262
+ โ”œโ”€ setup.cfg
263
+ โ”œโ”€ setup.py
264
+ โ”œโ”€ src/
265
+ โ”‚ โ””โ”€ proctap/
266
+ โ”‚ โ”œโ”€ __init__.py
267
+ โ”‚ โ”œโ”€ core.py
268
+ โ”‚ โ”œโ”€ _native.cpp
269
+ โ”‚ โ””โ”€ _native.pyi
270
+ โ”œโ”€ examples/
271
+ โ”‚ โ””โ”€ record_proc_to_wav.py
272
+ โ””โ”€ .github/
273
+ โ””โ”€ workflows/
274
+ โ””โ”€ build-wheels.yml
275
+ ```
276
+
277
+ ---
278
+
279
+ ## ๐Ÿ›  GitHub Action (Wheel Build)
280
+
281
+ ```yaml
282
+ name: Build and publish wheels
283
+
284
+ on:
285
+ push:
286
+ tags:
287
+ - "v*.*.*"
288
+ workflow_dispatch: {}
289
+
290
+ jobs:
291
+ build-wheels:
292
+ runs-on: windows-latest
293
+
294
+ strategy:
295
+ matrix:
296
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
297
+
298
+ steps:
299
+ - uses: actions/checkout@v4
300
+
301
+ - name: Setup Python
302
+ uses: actions/setup-python@v5
303
+ with:
304
+ python-version: ${{ matrix.python-version }}
305
+
306
+ - name: Install build tools
307
+ run: |
308
+ pip install --upgrade pip
309
+ pip install build
310
+
311
+ - name: Build wheel
312
+ run: |
313
+ python -m build --wheel
314
+
315
+ - name: Upload artifact
316
+ uses: actions/upload-artifact@v4
317
+ with:
318
+ name: wheels-py${{ matrix.python-version }}
319
+ path: dist/*.whl
320
+
321
+ publish:
322
+ needs: build-wheels
323
+ runs-on: ubuntu-latest
324
+ if: startsWith(github.ref, 'refs/tags/v')
325
+ steps:
326
+ - uses: actions/download-artifact@v4
327
+ with:
328
+ path: dist
329
+
330
+ - name: Flatten wheels
331
+ shell: bash
332
+ run: |
333
+ mkdir -p upload
334
+ find dist -name '*.whl' -exec cp {} upload/ \;
335
+
336
+ - name: Publish to PyPI
337
+ uses: pypa/gh-action-pypi-publish@v1.12.4
338
+ with:
339
+ user: __token__
340
+ password: ${{ secrets.PYPI_API_TOKEN }}
341
+ packages_dir: upload
342
+ ```
343
+
344
+ ---
345
+
346
+ ## ๐Ÿค Contributing
347
+
348
+ Contributions are welcome!
349
+
350
+ - Bug fixes
351
+ - Feature requests
352
+ - Performance improvements
353
+ - Type hints / async extension
354
+ - Documentation improvements
355
+
356
+ PRs from WASAPI/C++ experts are especially appreciated.
357
+
358
+ ---
359
+
360
+ ## ๐Ÿ“„ License
361
+
362
+ ```
363
+ MIT License
364
+ ```
365
+
366
+ ---
367
+
368
+ ## ๐Ÿ‘ค Author
369
+
370
+ **Yusuke Harada (m96-chan)**
371
+ Windows Audio / VRChat Tools / Python / C++
372
+ https://github.com/m96-chan
373
+