Skip to main content

cjm-vad-adapter-interface

Install

pip install cjm_vad_adapter_interface

Project Structure

nbs/
├── adapter.ipynb # The typed voice-activity-detection task contract — the `VADAdapter` ABC + the `VADToolProtocol` structural contract (capability-unit Option C, pass-2 Thread 3).
├── generic.ipynb # The generic (tool-agnostic) VAD adapter — cache-check, invoke the bound tool's pure-compute `detect_speech`, persist. Reused across every tool capability satisfying `VADToolProtocol`, exactly as `GenericTranscriptionAdapter` is reused across transcribers.
└── storage.ipynb # Standardized SQLite storage for voice-activity-detection results with content hashing.

Total: 3 notebooks

Module Dependencies

graph LR
    adapter["adapter<br/>VAD Adapter"]
    generic["generic<br/>Generic VAD Adapter"]
    storage["storage<br/>VAD Storage"]

    generic --> adapter
    generic --> storage

2 cross-module dependencies detected

CLI Reference

No CLI commands found in this project.

Module Overview

Detailed documentation for each module in the project:

VAD Adapter (adapter.ipynb)

The typed voice-activity-detection task contract — the VADAdapter ABC + the VADToolProtocol structural contract (capability-unit Option C, pass-2 Thread 3).

Import

from cjm_vad_adapter_interface.adapter import (
    VADToolProtocol,
    VADAdapter
)

Classes

@runtime_checkable
class VADToolProtocol(Protocol):
    """
    Structural contract for voice-activity-detection tool capabilities
    (born-final at stage 8 — derived from the native tool surface).
    
    Pure compute: `detect_speech` reads the model-ready audio + runs inference +
    builds the typed result. `get_current_config` supplies the effective config
    the generic adapter hashes for its cache key. Persistence is NOT here — the
    adapter owns it (the native-surface seam).
    """
    
    def detect_speech(self, audio: Union[str, Path], **kwargs) -> VADResult: ...
        def get_current_config(self) -> Dict[str, Any]: ...
    
    def get_current_config(self) -> Dict[str, Any]: ...
class VADAdapter:
    def __init__(
        self,
        tool: VADToolProtocol,  # The bound tool capability instance (worker-side binding)
    )
    """
    Typed voice-activity-detection task adapter: model-ready audio in,
    `VADResult` out.
    
    Input contract: the caller guarantees MODEL-READY audio — format /
    sample-rate / channel handling happens upstream (ffmpeg `convert`), never
    in the adapter or tool.
    
    Native-surface model (stage 8 / PILLAR 1c): the TOOL is pure compute; the
    ADAPTER owns the cache + persistence bookends (see `GenericVADAdapter`) +
    the per-call `force` control. Storage resolves from the substrate-injected
    `PLUGIN_DATA_DIR`; `db_path` is not on the tool protocol.
    
    Implementations run in-worker beside their tool capability and are
    constructed with the bound tool instance: `AdapterClass(tool)` (mirrors
    `GraphStorageAdapter`). The result DTO is wire-registered ("vad.result"):
    returned values cross the worker boundary typed.
    """
    
    def __init__(
            self,
            tool: VADToolProtocol,  # The bound tool capability instance (worker-side binding)
        )
    
    def detect_speech(
            self,
            audio: Union[str, Path],  # Path to MODEL-READY audio (converted upstream)
            **kwargs,                 # Provenance + tool options
        ) -> VADResult:               # Typed VAD output
        "Detect speech segments in model-ready audio."

Generic VAD Adapter (generic.ipynb)

The generic (tool-agnostic) VAD adapter — cache-check, invoke the bound tool’s pure-compute detect_speech, persist. Reused across every tool capability satisfying VADToolProtocol, exactly as GenericTranscriptionAdapter is reused across transcribers.

Import

from cjm_vad_adapter_interface.generic import (
    GenericVADAdapter
)

Classes

class GenericVADAdapter(VADAdapter):
    """
    Generic VAD adapter: cache-check -> pure-compute tool -> persist.
    
    Works against ANY tool satisfying `VADToolProtocol`. The bookends:
    
      1. cache check (file_path + file_hash + config_hash) BEFORE invoking the
         tool, so a hit never loads the model;
      2. the tool's pure-compute `detect_speech` on a miss / forced call;
      3. `save_with_logging` (upsert by file_path + config_hash).
    
    `config_hash` reuses `hash_dict_canonical(get_current_config())` (the SAME
    canonical hash the fused-era plugin used). `force` rides
    `CallEnvelope.control` (not a task kwarg, keeping `detect_speech(audio)`
    pure). Storage lives at `<PLUGIN_DATA_DIR>/vad.db`; the substrate injects
    the per-capability `PLUGIN_DATA_DIR` at spawn, so the adapter neither
    hard-codes a path nor asks the tool for one.
    """
    
    def detect_speech(
            self,
            audio: Union[str, Path],  # Path to MODEL-READY audio (converted upstream)
            **kwargs,                 # Provenance + tool options
        ) -> VADResult:               # Typed VAD output
        "Cache-check, invoke the bound tool's pure-compute `detect_speech`, persist."

VAD Storage (storage.ipynb)

Standardized SQLite storage for voice-activity-detection results with content hashing.

Import

from cjm_vad_adapter_interface.storage import (
    VADRow,
    VADStorage
)

Classes

@dataclass
class VADRow:
    "A single row from the vad_results table."
    
    file_path: str  # Path to the analyzed (model-ready) audio file
    file_hash: str  # Hash of the analyzed file in "algo:hexdigest" format
    config_hash: str  # Hash of the VAD detection config used
    ranges: Optional[List[Dict[str, Any]]]  # Detected speech segments (serialized TimeRanges)
    metadata: Optional[Dict[str, Any]]  # VAD metadata
    created_at: Optional[float]  # Unix timestamp
class VADStorage:
    def __init__(
        self,
        db_path: str  # Absolute path to the SQLite database file
    )
    "Standardized SQLite storage for voice-activity-detection results."
    
    def __init__(
            self,
            db_path: str  # Absolute path to the SQLite database file
        )
        "Initialize storage and create table if needed."
    
    def save(
            self,
            file_path: str,     # Path to the analyzed audio file
            file_hash: str,     # Hash of the analyzed file in "algo:hexdigest" format
            config_hash: str,   # Hash of the VAD detection config
            ranges: Optional[List[Dict[str, Any]]] = None,  # Detected speech segments
            metadata: Optional[Dict[str, Any]] = None        # VAD metadata
        ) -> None
        "Save or replace a VAD result (upsert by file_path + config_hash)."
    
    def save_with_logging(
            self,
            *,
            file_path: str,     # Path to the analyzed audio file
            file_hash: str,     # Hash of the analyzed file in "algo:hexdigest" format
            config_hash: str,   # Hash of the VAD detection config
            ranges: Optional[List[Dict[str, Any]]] = None,  # Detected speech segments
            metadata: Optional[Dict[str, Any]] = None,       # VAD metadata
            logger: Optional[logging.Logger] = None           # Optional logger for success/failure messages
        ) -> bool:  # True if saved; False if the save failed (error logged, not raised)
        "Save a result, logging success/failure. Failures are logged and swallowed (returns False).

CR-14 follow-up: records a RESULT_SAVED account either way (ok flag +
file/config references  the journal never carries content) so saves AND
swallowed save-failures become auditable journal rows."
    
    def get_cached(
            self,
            file_path: str,   # Path to the audio file
            file_hash: str,   # Content hash of the file (cache miss if the file changed)
            config_hash: str  # Config hash to match
        ) -> Optional[VADRow]:  # Cached row or None
        "Retrieve a content-correct cached VAD result.

Matches on file_path + file_hash + config_hash, so a changed file (new
file_hash) misses the cache even though a stale row may still exist at the
same (file_path, config_hash)  the next save() replaces it.

CR-14 follow-up: a hit records a CACHE_HIT account (the cache-serving
decision is an account-of-action)."
    
    def list_jobs(
            self,
            limit: int = 100  # Maximum number of rows to return
        ) -> List[VADRow]:  # List of VAD rows
        "List VAD results ordered by creation time (newest first)."
    
    def verify_file(
            self,
            file_path: str,   # Path to the audio file
            config_hash: str  # Config hash to look up
        ) -> Optional[bool]:  # True if file matches, False if changed, None if not found
        "Verify the analyzed file still matches the hash stored for (file_path, config_hash)."

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cjm_vad_adapter_interface-0.0.5.tar.gz (12.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cjm_vad_adapter_interface-0.0.5-py3-none-any.whl (15.8 kB view details)

Uploaded Python 3

File details

Details for the file cjm_vad_adapter_interface-0.0.5.tar.gz.

File metadata

File hashes

Hashes for cjm_vad_adapter_interface-0.0.5.tar.gz
Algorithm Hash digest
SHA256 6613439646dcdaec8d54180073d1e6edad90eab021fe30b750ed3f5d93c7bab6
MD5 90f487de33bdacda5f1c1651cf3ef2a2
BLAKE2b-256 5e1dc59d914791f1f764ea0aacb5929ffd621d83b28c8d906f2a51e3a30b4801

See more details on using hashes here.

File details

Details for the file cjm_vad_adapter_interface-0.0.5-py3-none-any.whl.

File metadata

File hashes

Hashes for cjm_vad_adapter_interface-0.0.5-py3-none-any.whl
Algorithm Hash digest
SHA256 6518a7cc26824795ee594c9832dbe73bb478dc6537793f30745938dab895a9c2
MD5 d514b0667a62df70c200b375368fd73f
BLAKE2b-256 265b39aa4bff7a859a698e5f9c39fee02e9b67c3c08e2383d6f2d78b895f6c40

See more details on using hashes here.

Release history Release notifications | RSS feed

0.0.10

2 files

0.0.9

2 files

0.0.8

2 files

0.0.7

2 files

0.0.6

2 files

This release

0.0.5 This release

2 files

0.0.4

2 files

0.0.3

2 files

0.0.2

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page