avioflow 0.1.7__cp39-cp39-manylinux_2_28_x86_64.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.
- avioflow/__init__.py +11 -0
- avioflow/_avioflow.cpython-39-x86_64-linux-gnu.so +0 -0
- avioflow/libavcodec.so.61.19.100 +0 -0
- avioflow/libavdevice.so.61.3.100 +0 -0
- avioflow/libavfilter.so.10.4.100 +0 -0
- avioflow/libavformat.so.61.7.100 +0 -0
- avioflow/libavioflow.so +0 -0
- avioflow/libavutil.so.59.39.100 +0 -0
- avioflow/libswresample.so.5.3.100 +0 -0
- avioflow/libswscale.so.8.3.100 +0 -0
- avioflow-0.1.7.dist-info/METADATA +354 -0
- avioflow-0.1.7.dist-info/RECORD +14 -0
- avioflow-0.1.7.dist-info/WHEEL +5 -0
- avioflow.libs/libdrm-b0291a67.so.2.4.0 +0 -0
avioflow/__init__.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
# On Windows, we need to add the package directory to the DLL search path
|
|
5
|
+
# so that the FFmpeg DLLs can be found.
|
|
6
|
+
if sys.platform == "win32" and sys.version_info >= (3, 8):
|
|
7
|
+
pkg_dir = os.path.dirname(__file__)
|
|
8
|
+
if os.path.isdir(pkg_dir):
|
|
9
|
+
os.add_dll_directory(pkg_dir)
|
|
10
|
+
|
|
11
|
+
from ._avioflow import *
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
avioflow/libavioflow.so
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: avioflow
|
|
3
|
+
Version: 0.1.7
|
|
4
|
+
Summary: High-performance audio decoding with FFmpeg and C++
|
|
5
|
+
Author: lxp3
|
|
6
|
+
License: MIT
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
15
|
+
Classifier: Programming Language :: C++
|
|
16
|
+
Classifier: Topic :: Multimedia :: Sound/Audio
|
|
17
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
18
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
19
|
+
Requires-Python: >=3.8
|
|
20
|
+
Requires-Dist: numpy
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
# AvioFlow
|
|
24
|
+
|
|
25
|
+
High-performance audio decoding library powered by FFmpeg with C++, Python, and Node.js bindings.
|
|
26
|
+
|
|
27
|
+
## Features
|
|
28
|
+
|
|
29
|
+
- **Multi-format Support**: MP3, WAV, AAC, FLAC, Opus, and all FFmpeg-supported formats
|
|
30
|
+
- **Flexible Input**: Files, URLs, memory buffers, and real-time streams
|
|
31
|
+
- **Hardware Capture**: WASAPI loopback (system audio) and DirectShow (microphones)
|
|
32
|
+
- **Resampling**: Built-in sample rate and channel conversion
|
|
33
|
+
- **Zero-copy API**: Direct buffer access via `FrameData` for maximum performance
|
|
34
|
+
- **Cross-platform**: Windows, Linux, macOS
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Installation
|
|
39
|
+
|
|
40
|
+
### Python
|
|
41
|
+
```bash
|
|
42
|
+
pip install avioflow
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Node.js
|
|
46
|
+
```bash
|
|
47
|
+
npm install avioflow
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### C++ (CMake)
|
|
51
|
+
```cmake
|
|
52
|
+
find_package(avioflow REQUIRED)
|
|
53
|
+
target_link_libraries(your_target avioflow::avioflow)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## C++ API
|
|
59
|
+
|
|
60
|
+
### Core Classes
|
|
61
|
+
|
|
62
|
+
#### `AudioDecoder`
|
|
63
|
+
|
|
64
|
+
Main class for audio decoding.
|
|
65
|
+
|
|
66
|
+
```cpp
|
|
67
|
+
#include "avioflow-cxx-api.h"
|
|
68
|
+
using namespace avioflow;
|
|
69
|
+
|
|
70
|
+
// Constructor options
|
|
71
|
+
AudioStreamOptions options;
|
|
72
|
+
options.output_sample_rate = 16000; // Target sample rate
|
|
73
|
+
options.output_num_channels = 1; // Target channels
|
|
74
|
+
options.input_format = "s16le"; // For streaming: source format
|
|
75
|
+
options.input_sample_rate = 48000; // For streaming: source rate
|
|
76
|
+
options.input_channels = 2; // For streaming: source channels
|
|
77
|
+
|
|
78
|
+
AudioDecoder decoder(options);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
#### Methods
|
|
82
|
+
|
|
83
|
+
| Method | Description |
|
|
84
|
+
|--------|-------------|
|
|
85
|
+
| `open(source)` | Open file path, URL, or device |
|
|
86
|
+
| `push(data, size)` | Push raw bytes for streaming decode |
|
|
87
|
+
| `decode_next()` | Decode next frame, returns `FrameData` |
|
|
88
|
+
| `get_all_samples()` | Decode all and return `vector<vector<float>>` |
|
|
89
|
+
| `get_metadata()` | Get audio metadata |
|
|
90
|
+
| `is_finished()` | Check if EOF reached |
|
|
91
|
+
|
|
92
|
+
#### `FrameData`
|
|
93
|
+
|
|
94
|
+
Zero-copy frame data structure returned by `decode_next()`.
|
|
95
|
+
|
|
96
|
+
```cpp
|
|
97
|
+
struct FrameData {
|
|
98
|
+
float** data; // Planar channel pointers: data[channel][sample]
|
|
99
|
+
int num_channels; // Number of channels
|
|
100
|
+
int num_samples; // Samples per channel
|
|
101
|
+
|
|
102
|
+
operator bool(); // True if valid data
|
|
103
|
+
};
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
> ⚠️ **Warning**: `FrameData.data` points to internal buffer, valid only until next `decode_next()` call.
|
|
107
|
+
|
|
108
|
+
### Examples
|
|
109
|
+
|
|
110
|
+
#### File Decoding (Offline)
|
|
111
|
+
```cpp
|
|
112
|
+
AudioDecoder decoder({.output_sample_rate = 16000});
|
|
113
|
+
decoder.open("audio.mp3");
|
|
114
|
+
|
|
115
|
+
auto samples = decoder.get_all_samples(); // vector<vector<float>>
|
|
116
|
+
std::cout << "Channels: " << samples.size() << std::endl;
|
|
117
|
+
std::cout << "Samples: " << samples[0].size() << std::endl;
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### Frame-by-Frame Decoding
|
|
121
|
+
```cpp
|
|
122
|
+
AudioDecoder decoder;
|
|
123
|
+
decoder.open("audio.mp3");
|
|
124
|
+
|
|
125
|
+
while (auto frame = decoder.decode_next()) {
|
|
126
|
+
// frame.data[channel][sample]
|
|
127
|
+
for (int c = 0; c < frame.num_channels; c++) {
|
|
128
|
+
process(frame.data[c], frame.num_samples);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
#### Streaming Decode (Push-based)
|
|
134
|
+
```cpp
|
|
135
|
+
AudioStreamOptions opts;
|
|
136
|
+
opts.input_format = "s16le";
|
|
137
|
+
opts.input_sample_rate = 48000;
|
|
138
|
+
opts.input_channels = 2;
|
|
139
|
+
|
|
140
|
+
AudioDecoder decoder(opts);
|
|
141
|
+
decoder.push(raw_bytes, size); // Auto-initializes on first call
|
|
142
|
+
|
|
143
|
+
while (auto frame = decoder.decode_next()) {
|
|
144
|
+
// Process decoded audio...
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
#### WASAPI Loopback Capture
|
|
149
|
+
```cpp
|
|
150
|
+
AudioDecoder decoder;
|
|
151
|
+
decoder.open("wasapi_loopback");
|
|
152
|
+
|
|
153
|
+
while (auto frame = decoder.decode_next()) {
|
|
154
|
+
// Capture system audio in real-time
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Python API
|
|
161
|
+
|
|
162
|
+
### `AudioDecoder`
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
import avioflow
|
|
166
|
+
|
|
167
|
+
# Constructor with keyword arguments
|
|
168
|
+
decoder = avioflow.AudioDecoder(
|
|
169
|
+
output_sample_rate=16000, # Optional: target sample rate
|
|
170
|
+
output_num_channels=1, # Optional: target channels
|
|
171
|
+
input_format="s16le", # For streaming: source format
|
|
172
|
+
input_sample_rate=48000, # For streaming: source rate
|
|
173
|
+
input_channels=2 # For streaming: source channels
|
|
174
|
+
)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
#### Methods
|
|
178
|
+
|
|
179
|
+
| Method | Returns | Description |
|
|
180
|
+
|--------|---------|-------------|
|
|
181
|
+
| `load(source)` | `Metadata` | Load file, URL, or `pathlib.Path` |
|
|
182
|
+
| `decoder(bytes)` | `ndarray` | Push bytes and decode (streaming) |
|
|
183
|
+
| `get_all_samples()` | `ndarray` | Decode entire source |
|
|
184
|
+
| `is_finished()` | `bool` | Check if EOF |
|
|
185
|
+
|
|
186
|
+
#### `Metadata`
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
meta = decoder.load("audio.mp3")
|
|
190
|
+
print(f"Duration: {meta.duration}s")
|
|
191
|
+
print(f"Sample Rate: {meta.sample_rate}Hz")
|
|
192
|
+
print(f"Channels: {meta.num_channels}")
|
|
193
|
+
print(f"Codec: {meta.codec}")
|
|
194
|
+
print(f"Container: {meta.container}")
|
|
195
|
+
print(f"Bit Rate: {meta.bit_rate}bps")
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Examples
|
|
199
|
+
|
|
200
|
+
#### File Decoding
|
|
201
|
+
```python
|
|
202
|
+
decoder = avioflow.AudioDecoder(output_sample_rate=16000)
|
|
203
|
+
meta = decoder.load("speech.wav")
|
|
204
|
+
samples = decoder.get_all_samples() # numpy array (channels, samples)
|
|
205
|
+
print(f"Shape: {samples.shape}") # e.g., (1, 160000)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
#### Streaming Decode
|
|
209
|
+
```python
|
|
210
|
+
decoder = avioflow.AudioDecoder(
|
|
211
|
+
input_format="s16le",
|
|
212
|
+
input_sample_rate=48000,
|
|
213
|
+
input_channels=2
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
while True:
|
|
217
|
+
data = socket.recv(4096)
|
|
218
|
+
samples = decoder(data) # Call decoder directly
|
|
219
|
+
if samples.size > 0:
|
|
220
|
+
process_audio(samples)
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
#### Device Discovery
|
|
224
|
+
```python
|
|
225
|
+
devices = avioflow.DeviceManager.list_audio_devices()
|
|
226
|
+
for dev in devices:
|
|
227
|
+
print(f"{dev.name}: {dev.description}")
|
|
228
|
+
# dev.is_output: True for output/loopback devices
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Logging
|
|
232
|
+
```python
|
|
233
|
+
avioflow.set_log_level("debug") # quiet, error, warning, info, debug, trace
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Node.js API
|
|
239
|
+
|
|
240
|
+
### ESM Import
|
|
241
|
+
```javascript
|
|
242
|
+
import avioflow from 'avioflow';
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### `AudioDecoder`
|
|
246
|
+
|
|
247
|
+
```javascript
|
|
248
|
+
// Constructor with options object
|
|
249
|
+
const decoder = new avioflow.AudioDecoder({
|
|
250
|
+
outputSampleRate: 16000, // Optional
|
|
251
|
+
outputNumChannels: 1, // Optional
|
|
252
|
+
inputFormat: 's16le', // For streaming
|
|
253
|
+
inputSampleRate: 48000, // For streaming
|
|
254
|
+
inputChannels: 2 // For streaming
|
|
255
|
+
});
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
#### Methods
|
|
259
|
+
|
|
260
|
+
| Method | Returns | Description |
|
|
261
|
+
|--------|---------|-------------|
|
|
262
|
+
| `load(source)` | `Metadata` | Load file or URL |
|
|
263
|
+
| `push(buffer)` | `void` | Push raw bytes for streaming |
|
|
264
|
+
| `decodeNext()` | `Float32Array[]` or `null` | Decode next frame |
|
|
265
|
+
| `getMetadata()` | `Metadata` | Get audio metadata |
|
|
266
|
+
| `isFinished()` | `boolean` | Check if EOF |
|
|
267
|
+
|
|
268
|
+
### Examples
|
|
269
|
+
|
|
270
|
+
#### File Decoding
|
|
271
|
+
```javascript
|
|
272
|
+
const decoder = new avioflow.AudioDecoder({ outputSampleRate: 16000 });
|
|
273
|
+
const meta = decoder.load("audio.mp3");
|
|
274
|
+
console.log(`Duration: ${meta.duration}s, Channels: ${meta.numChannels}`);
|
|
275
|
+
|
|
276
|
+
while (!decoder.isFinished()) {
|
|
277
|
+
const frame = decoder.decodeNext();
|
|
278
|
+
if (frame) {
|
|
279
|
+
// frame is array of Float32Array (one per channel)
|
|
280
|
+
console.log(`Decoded ${frame[0].length} samples`);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
#### Streaming Decode
|
|
286
|
+
```javascript
|
|
287
|
+
const decoder = new avioflow.AudioDecoder({
|
|
288
|
+
inputFormat: 's16le',
|
|
289
|
+
inputSampleRate: 48000,
|
|
290
|
+
inputChannels: 2
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
socket.on('data', (chunk) => {
|
|
294
|
+
decoder.push(chunk);
|
|
295
|
+
let frame;
|
|
296
|
+
while ((frame = decoder.decodeNext()) !== null) {
|
|
297
|
+
processAudio(frame);
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
#### Device Discovery
|
|
303
|
+
```javascript
|
|
304
|
+
const devices = avioflow.listAudioDevices();
|
|
305
|
+
devices.forEach(dev => {
|
|
306
|
+
console.log(`${dev.isOutput ? 'Output' : 'Input'}: ${dev.name}`);
|
|
307
|
+
});
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
## Build from Source
|
|
313
|
+
|
|
314
|
+
### Prerequisites
|
|
315
|
+
- CMake 3.20+
|
|
316
|
+
- Visual Studio 2022+ (Windows) or GCC 11+ (Linux)
|
|
317
|
+
- Python 3.8+ with pybind11 (for Python bindings)
|
|
318
|
+
- Node.js 16+ (for Node.js bindings)
|
|
319
|
+
|
|
320
|
+
### Windows
|
|
321
|
+
```powershell
|
|
322
|
+
.\build.ps1
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Linux
|
|
326
|
+
```bash
|
|
327
|
+
cmake -B build -DENABLE_PYTHON=ON
|
|
328
|
+
cmake --build build --config Release
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### Node.js Prebuild
|
|
332
|
+
```bash
|
|
333
|
+
npm run prebuild
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## Input Format Reference
|
|
339
|
+
|
|
340
|
+
| Format | Description | Use Case |
|
|
341
|
+
|--------|-------------|----------|
|
|
342
|
+
| `s16le` | 16-bit signed PCM, little-endian | Raw audio, WebRTC |
|
|
343
|
+
| `s16be` | 16-bit signed PCM, big-endian | Network streams |
|
|
344
|
+
| `f32le` | 32-bit float PCM, little-endian | High-quality audio |
|
|
345
|
+
| `aac` | AAC with ADTS headers | Streaming AAC |
|
|
346
|
+
| `mp3` | MP3 frames | Streaming MP3 |
|
|
347
|
+
| `opus` | Opus packets | WebRTC, VoIP |
|
|
348
|
+
| `wav` | WAV container | File-based audio |
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
## License
|
|
353
|
+
|
|
354
|
+
MIT License
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
avioflow/libavutil.so.59.39.100,sha256=zC9KmN6NQ3ufxi3tsO9a3ZetcG1uB5OUaoRrTa-0zBA,1070473
|
|
2
|
+
avioflow/libavfilter.so.10.4.100,sha256=iJRks3G4_qeaQ4-FETpEkE3WbvXcwXuf7xuImftcQBg,213465
|
|
3
|
+
avioflow/libavcodec.so.61.19.100,sha256=_i_9KVKPnyjYzRJWozCrdXLy-UoiAtuveYPSUsM9zgw,1687417
|
|
4
|
+
avioflow/libavdevice.so.61.3.100,sha256=tVSrsSGkzQHog-Zr8egorw2N9pFqcfvg4BtLayLIGlA,110049
|
|
5
|
+
avioflow/libswscale.so.8.3.100,sha256=YPtLFVZKYdnZ8VTuKJBj5UTzPyF4hmilTIloAW9aJQI,659313
|
|
6
|
+
avioflow/libavioflow.so,sha256=I2pnsZUOGucUXlhpe4sXhMUHVnIh4q8C8pbB50QZYmM,61601
|
|
7
|
+
avioflow/libavformat.so.61.7.100,sha256=OAgAxCAPFdPQEA4RvHJGPxQ49iuCjt6QCBXAZU2h3u0,770929
|
|
8
|
+
avioflow/libswresample.so.5.3.100,sha256=g7SxrmgQ9kQm9THylQKc8CkfQ6vcEJbd2B1ixamJXS8,145265
|
|
9
|
+
avioflow/__init__.py,sha256=FvMzjMYg6BF6EsoenDh8EJfAKUdZuw7OSsPi0RPS9Fk,330
|
|
10
|
+
avioflow/_avioflow.cpython-39-x86_64-linux-gnu.so,sha256=HZX3l3Os25baMU6CfhQi1GW22pQZZmbduRuUTfry6Y0,246913
|
|
11
|
+
avioflow-0.1.7.dist-info/WHEEL,sha256=xquIjRFKi8eOGZiAYswPXkxWLvbe_GJsWqwM9Hp14NM,116
|
|
12
|
+
avioflow-0.1.7.dist-info/METADATA,sha256=TIpfmQH5tKUUU6ik9yFzRz-uSxMpx8aSeHT3ZDCH190,8764
|
|
13
|
+
avioflow-0.1.7.dist-info/RECORD,,
|
|
14
|
+
avioflow.libs/libdrm-b0291a67.so.2.4.0,sha256=K48ZAlNAuvSdX7i2toETxCm6886w4E17JmP2c8RM2-0,96417
|
|
Binary file
|