ruopus encodes and decodes Opus audio
(RFC 6716) with first-class NumPy
interop. The codec itself is a from-scratch Rust implementation with no C and
no FFI, but day to day you just call Python methods that take and return
NumPy arrays - the Rust is an implementation detail.
Features
- Encode and decode: automatic mode selection (SILK / hybrid / CELT) with full control over bitrate, complexity, DTX, in-band FEC, bandwidth, and application profile
- NumPy native: PCM crosses the boundary as
(frames, channels)float32 (or int16) arrays, moved out of Rust with no extra copy - No GIL stalls: every encode/decode call releases the GIL
- Ogg Opus files: single-call
encode_ogg_opus/decode_ogg_opusfor complete.opusfiles - Packet loss handling: concealment (
decode_lost) and in-band FEC recovery (decode_fec) - Packet introspection: parse the TOC byte and frame structure of raw Opus packets without decoding audio
- Surround: multistream decoding for 5.1/7.1 and other RFC 7845 layouts
- Low-level access: the
ruopus.lowlevelsubmodule exposes the SILK and CELT codecs and the LPC analysis pipeline directly, for research and custom codec work - Fully typed: ships with
.pyistubs and apy.typedmarker
Installation
pip install ruopus
Requires Python 3.9+ and NumPy 1.22+. Pre-built wheels are available for Linux, macOS, and Windows (CPython 3.9-3.13) - no Rust toolchain needed.
Quick Start
import numpy as np
import ruopus
# Stereo encoder at 64 kbps, matching decoder
enc = ruopus.OpusEncoder(2, bitrate=64_000)
dec = ruopus.OpusDecoder(2)
# 20 ms stereo frame at 48 kHz -> 960 samples per channel
frame = np.zeros((960, 2), dtype=np.float32)
packet = enc.encode_auto(frame) # bytes - encoded Opus packet
pcm = dec.decode_packet(packet) # (960, 2) float32 in [-1, 1]
Encoder input can be a 1-D interleaved array or a 2-D (frames, channels)
array; both are accepted without extra copies.
Ogg Opus Files
Write and read complete .opus files in one call each:
import numpy as np
import ruopus
sr = 48_000
t = np.linspace(0, 3, sr * 3, dtype=np.float32)
pcm = np.column_stack([
np.sin(2 * np.pi * 440 * t), # left: A4
np.sin(2 * np.pi * 880 * t), # right: A5
])
ogg = ruopus.encode_ogg_opus(pcm, channels=2, bitrate=128_000)
with open("output.opus", "wb") as f:
f.write(ogg)
with open("output.opus", "rb") as f:
decoded_pcm, head = ruopus.decode_ogg_opus(f.read())
print(f"{head.channel_count}-ch, {decoded_pcm.shape[0] / sr:.2f}s")
Packet Loss and FEC
import ruopus
dec = ruopus.OpusDecoder(2)
FRAME = 960 # 20 ms at 48 kHz
for pkt in stream:
if pkt is None:
pcm = dec.decode_lost(frame_size=FRAME) # concealment
else:
pcm = dec.decode_packet(pkt)
# Recover a lost packet from in-band FEC carried by its successor
recovered = dec.decode_fec(next_pkt, frame_size=FRAME)
Choosing a Bitrate and Application
# Phone-quality voice
enc_voice = ruopus.OpusEncoder(
1,
bitrate=8_000,
application=ruopus.Application.Voip,
signal=ruopus.Signal.Voice,
)
# High-quality music
enc_music = ruopus.OpusEncoder(
2,
bitrate=128_000,
application=ruopus.Application.Audio,
signal=ruopus.Signal.Music,
)
# Low-latency game voice (CELT only)
enc_ld = ruopus.OpusEncoder(
1,
bitrate=32_000,
application=ruopus.Application.RestrictedLowDelay,
)
Surround Decoding
import ruopus
# 5.1 surround: 4 elementary streams, 2 stereo-coupled
dec = ruopus.MultistreamDecoder(
streams=4,
coupled=2,
mapping=[0, 4, 1, 2, 3, 5], # L R C LFE Ls Rs
)
pcm = dec.decode_packet(raw_packet) # (frames, 6) float32
Packet Inspection
import ruopus
pkt = ruopus.Packet(raw_bytes)
print(f"mode={pkt.toc.mode}, bandwidth={pkt.toc.bandwidth}, frames={len(pkt)}")
Low-Level API
For research or custom codec work, ruopus.lowlevel exposes the SILK and
CELT layers and the LPC analysis pipeline directly, below the Opus packet
format:
import numpy as np
import ruopus.lowlevel as ll
enc = ll.CeltEncoder(channels=1, complexity=10, bitrate=64_000)
frame = np.zeros(960, dtype=np.float32)
body = enc.encode(frame) # raw CELT frame body, no Opus framing
Performance
Measured against libopus 1.6.1 (SIMD-enabled C), one core, pinned to a single performance core. Figures are x realtime.
| Mode | ruopus | libopus |
|---|---|---|
| Decode, SILK wideband 16 kb/s | 2095x | 1171x |
| Decode, CELT fullband 64 kb/s | 1389x | 1566x |
| Encode, matched complexity (all modes) | parity with libopus |
See the full benchmark breakdown for the complete table and methodology.
Documentation
The full guide and API reference are at jmg049.github.io/ruopus, covering codec modes, frame sizes, FEC/loss handling, multistream layouts, and the low-level API in depth.
License
MIT License.
Links
- GitHub: https://github.com/jmg049/ruopus
- Documentation: https://jmg049.github.io/ruopus/
- PyPI: https://pypi.org/project/ruopus/
Metadata
Release files for ruopus 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| ruopus-0.1.2.tar.gz | 337.8 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ruopus-0.1.2-cp313-cp313-manylinux_2_34_x86_64.whl | CPython 3.13 | CPython 3.13 | Linux glibc 2.34+ x86-64 | Details |
Total release size: 1.3 MB
Release files / ruopus-0.1.2.tar.gz
| Download URL | ruopus-0.1.2.tar.gz |
|---|---|
| Size | 337.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
40cb87bd6be2842fb3feb6683f0c9edaf9bddc97cb818601cb6a90e08f9ada3c
|
|
BLAKE2b-256 checksum How to use checksums |
2ca8476587d0d527f0e7dfd33fc6ec4a2534e71f2976b436bea107de89258228
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|
Release files / ruopus-0.1.2-cp313-cp313-manylinux_2_34_x86_64.whl
| Download URL | ruopus-0.1.2-cp313-cp313-manylinux_2_34_x86_64.whl |
|---|---|
| Size | 1.0 MB |
| Tags | CPython 3.13 Linux glibc 2.34+ x86-64 |
|
SHA-256 checksum How to use checksums |
9610e4b9de3452dda0753b0d3c36cc7036fe9a5e3f8822e29829578da1ba7a17
|
|
BLAKE2b-256 checksum How to use checksums |
b8e42c37221482ad1064766e6b8a8964e1cf612bffcc4a230c0abcd71a434a9b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.14.1
|
Security for ruopus 0.1.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.