Typed voice-activity-detection task-adapter interface — VADAdapter ABC + GenericVADAdapter (cache/persist bookends around a pure-compute tool), the VADToolProtocol, and VAD persistence helpers. The VADResult data noun lives in cjm-capability-primitives.
Project description
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
VADAdapterABC + theVADToolProtocolstructural 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 satisfyingVADToolProtocol, exactly asGenericTranscriptionAdapteris 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)."
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cjm_vad_adapter_interface-0.0.4.tar.gz.
File metadata
- Download URL: cjm_vad_adapter_interface-0.0.4.tar.gz
- Upload date:
- Size: 12.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
34fda0afd589f58a885f1ed284f7ea41582b5fab6e0a4fd78d20519b6dc3e8b2
|
|
| MD5 |
9a02cd98ded1f41a841ad26d28e04594
|
|
| BLAKE2b-256 |
206c6c60adc02c65ac9b111dc380590fc22c7020541ea0a9ac314ed8be47b23e
|
File details
Details for the file cjm_vad_adapter_interface-0.0.4-py3-none-any.whl.
File metadata
- Download URL: cjm_vad_adapter_interface-0.0.4-py3-none-any.whl
- Upload date:
- Size: 15.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
894cd21f3829fde5f5a16399e94853f054aa57a5dc2d8cc286d33bf68049ac3f
|
|
| MD5 |
d9cf5dc32a7b3288ccd6b34b87b93907
|
|
| BLAKE2b-256 |
2947c5da01a62db3dadb007c3a71683155a659f5215e6bed73f915f2c478a9e3
|