"""DiariZen speaker diarization segmentation inference.""" import json import os from pathlib import Path from typing import Optional import numpy as np class DiarizenSegmenter: """Speaker diarization segmentation using NPU CNN frontend + CPU backend. Pipeline: 1. Audio preprocessing (resample + LayerNorm) on CPU. 2. CNN feature extraction on AX650 NPU (U16). 3. Transformer + Conformer + Classifier on CPU (ONNX Runtime). """ def __init__( self, cnn_model_path: str, backend_model_path: str, meta_path: Optional[str] = None, ): self._cnn_path = Path(cnn_model_path) self._backend_path = Path(backend_model_path) if meta_path is None: meta_path = Path(__file__).parent / "model_meta.json" with open(meta_path) as f: self._meta = json.load(f) pp = self._meta["preprocess"] self._sample_rate = pp["sample_rate"] self._duration_s = pp["duration_seconds"] self._eps = pp.get("layer_norm_eps", 1e-5) self._num_samples = int(self._sample_rate * self._duration_s) self._cnn_session = None self._backend_session = None def _init_cnn(self): """Initialize NPU CNN inference session.""" try: from axengine import InferenceSession except ImportError: raise RuntimeError( "pyaxengine is required for NPU inference. " "Install from: https://github.com/AXERA-TECH/pyaxengine" ) self._cnn_session = InferenceSession(str(self._cnn_path)) def _init_backend(self): """Initialize CPU backend ONNX inference session.""" import onnxruntime as ort self._backend_session = ort.InferenceSession( str(self._backend_path), providers=["CPUExecutionProvider"], ) def __call__(self, audio: np.ndarray, sample_rate: int) -> np.ndarray: """Run segmentation inference. Args: audio: 1-D float32 waveform. sample_rate: Original sample rate. Returns: Log-probabilities of shape (1, frames, 11), float32. """ from .preprocess import preprocess_audio waveform_ln = preprocess_audio( audio, sample_rate, target_sr=self._sample_rate, duration_s=self._duration_s, eps=self._eps, ) if self._cnn_session is None: self._init_cnn() cnn_outputs = self._cnn_session.run( {self._cnn_session.input_names()[0]: waveform_ln} ) cnn_features = cnn_outputs[0] if self._backend_session is None: self._init_backend() backend_inputs = { self._backend_session.get_inputs()[0].name: cnn_features } log_probs = self._backend_session.run(None, backend_inputs)[0] return log_probs @property def num_frames(self) -> int: return 199 @property def num_classes(self) -> int: return 11