Ogg Opus Files
Ogg Opus (RFC 7845) is the
standard container for Opus audio. ruopus provides two convenience functions,
encode_ogg_opus() and decode_ogg_opus(), that
handle the full container round-trip in a single call, plus the
OpusHead identification-header object returned by the decoder.
Encoding to Ogg Opus
encode_ogg_opus() takes raw 48 kHz float32 PCM and returns a
complete Ogg Opus file as bytes:
import numpy as np
import ruopus
# Generate 3 seconds of stereo audio
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
]) # shape (144000, 2)
ogg = ruopus.encode_ogg_opus(pcm, channels=2, bitrate=128_000)
with open("output.opus", "wb") as f:
f.write(ogg)
print(f"Ogg Opus file: {len(ogg) / 1024:.1f} KB")
Input can also be a 1-D interleaved array (samples interleaved L, R, L, R, …):
flat_pcm = pcm.ravel() # shape (288000,)
ogg = ruopus.encode_ogg_opus(flat_pcm, channels=2, bitrate=128_000)
Decoding from Ogg Opus
decode_ogg_opus() handles the complete demuxing pipeline:
Reads the
OpusHeadidentification headerApplies the
pre_skip(discards leading silence)Trims trailing granule padding
Applies the
output_gain_q8to the decoded PCM
with open("input.opus", "rb") as f:
data = f.read()
pcm, head = ruopus.decode_ogg_opus(data)
print(f"Channels: {head.channel_count}")
print(f"Input rate: {head.input_sample_rate} Hz")
print(f"Pre-skip: {head.pre_skip} samples")
print(f"Output gain: {head.output_gain_q8} (Q7.8 dB)")
print(f"Decoded PCM: {pcm.shape}, dtype={pcm.dtype}")
The output is always float32 at 48 kHz, shaped (frames, channels).
Reading the OpusHead
The OpusHead object exposes every field of the RFC 7845
identification header:
pcm, head = ruopus.decode_ogg_opus(data)
print(repr(head))
# OpusHead(version=1, channel_count=2, pre_skip=312,
# input_sample_rate=44100, mapping_family=0)
# Round-trip the header back to bytes (e.g. for remuxing):
header_bytes = head.to_bytes()
Channel-mapping family 0 (mono and stereo) is the only family currently
supported by decode_ogg_opus(). For surround layouts, see
Multistream Decoding.
Round-Trip Fidelity
A full encode → decode round-trip introduces the encoder lookahead (typically 120 samples) as latency and the codec’s lossy compression artifacts:
import numpy as np
import ruopus
original = np.random.randn(48_000).astype(np.float32)
ogg = ruopus.encode_ogg_opus(original, channels=1, bitrate=256_000)
decoded, head = ruopus.decode_ogg_opus(ogg)
# The decoded length may differ slightly due to pre_skip and frame alignment
min_len = min(len(original), len(decoded))
rms_err = np.sqrt(np.mean((original[:min_len] - decoded[:min_len, 0]) ** 2))
print(f"RMS error vs original: {rms_err:.6f}")
Saving Decoded Audio
The decoded float32 PCM can be saved with audio_samples:
import numpy as np
import audio_samples as aus
pcm, head = ruopus.decode_ogg_opus(data)
samples = aus.AudioSamples.new_mono(pcm, 48_000)
aus.io.save("decoded.wav", samples, as_type=np.float32)