RIVLET

Rivlet Listen SDK

Add voice to your product in 3 lines.

Adapts to your users without a cloud round-trip. Runs offline on a Raspberry Pi, a browser tab, a Linux server, or your existing Python service. One .rivlet file works in every binding.

Status: The Python wheel, C lib, Rust crate, and standalone binary are in active development (Phase 3 of the SaaS roadmap). The WASM binding (@rivlet/listen) ships next; native bindings follow. The full API spec below is the authoritative contract every binding implements.

3 lines, every language

pip install rivlet-listen

Quickstart

from rivlet_listen import Model

model = Model.load("doorbell.rivlet")
print(model.predict(audio_wav_bytes))
# → Prediction(label='doorbell', confidence=0.94, …)

Without us vs with us

Add voice classification to a Python service. The boilerplate version is real code we've seen in production. The Rivlet version is what you actually want to write.

Without — Picovoice + AWS Lex fallback (27 lines)

import os
import pvporcupine, pvrhino
import boto3

PICO_KEY = os.environ["PICOVOICE_ACCESS_KEY"]
porcupine = pvporcupine.create(
    access_key=PICO_KEY,
    keyword_paths=["./doorbell_en_mac_v2_2_0.ppn"],
)
rhino = pvrhino.create(
    access_key=PICO_KEY,
    context_path="./commands_en_mac_v2_2_0.rhn",
)

lex = boto3.client("lex-runtime-v2",
                    aws_access_key_id=os.environ["AWS_KEY"],
                    aws_secret_access_key=os.environ["AWS_SECRET"])

def classify(audio_pcm):
    if porcupine.process(audio_pcm) >= 0:
        return "doorbell"
    inference = rhino.process(audio_pcm)
    if inference.is_finalized:
        return inference.intent
    # Fall back to AWS Lex for OOV:
    resp = lex.recognize_utterance(
        botId=BOT_ID, botAliasId=ALIAS_ID,
        localeId="en_US", sessionId=SID,
        requestContentType="audio/x-l16; rate=16000",
        inputStream=audio_pcm,
    )
    return resp["interpretations"][0]["intent"]["name"]

# … plus error handling, API keys per env, billing dashboards in two places,
# .ppn / .rhn per-device licensing, AWS per-request fees, no adaptation, etc.

With Rivlet — 3 lines

from rivlet_listen import Model

model = Model.load("doorbell.rivlet")
print(model.predict(audio_wav_bytes))
Adapt to a specific user with model.adapt(corrections) — 1 more line.

How it compares

FeatureRivletPicovoiceMediaPipeDialogflow
Runs offlineyesyesyesno
Per-user adaptation built inyesnonono
Custom vocab without cloud retrainpartialnonon/a
Standalone micro-binary deliverableyesnonono
.rivlet portable across all bindingsyesnonon/a
Source-available SDKyesnoyesno
Per-device licensing feesnoyesnon/a

Per-language guides

Tutorials

Licensing

SDK source code is Apache 2.0 — fork it, audit it, ship it. .rivlet model blobs use the rivlet-format v2 container: zstd compression, AES-256-GCM encryption, Ed25519 signature, license-binding via HKDF, and field obfuscation so the payload structure isn't legible even to a valid licensee. Each binding decrypts via rivlet_format::unpack(blob, license_key, signing_pub). License keys are never sent anywhere by the SDK; they're local secrets used to derive the decryption key. No phone-home, no per-call ping. Cancel your subscription and your deployed .rivlet keeps working until its bundle expiry.

Weights alone aren't the whole product. The format raises the bar against casual extraction; the real moat is the proprietary substrate code and the developmental training process that produced the weights. We're transparent about this — see the strategic framing section of the format spec.

Ready to ship?

Free Hobby tier — one model, WASM bundle, no card. Developer tier ($49/mo) unlocks all bindings, all platforms, the standalone binary.