- SileroVAD actor: 512-sample chunk enforcement, opset-16 preferred with opset-15 fallback, stateful LSTM hidden vectors, VADDecision transitions - VADInferenceEngine protocol + TestableVADOpset seam for test injection - ORTVADEngine: real ORT-backed inference using OnnxRuntimeBindings - ContractParityProbe: scaffold-time synthetic waveform parity gate - VADError: invalidChunkSize / modelLoadFailed / opsetUnsupported / runFailed - Resources/models/silero/MANIFEST.json (SHA-256 placeholder — run fetch script) - scripts/fetch-silero-models.sh: downloads v6.2.1 ONNX models + updates hashes - .gitignore: *.onnx excluded from git - All S1..S6 tests pass (S5 skips when models absent — expected) - Rule 3 deviation: Package.swift target deps updated (ORT + WhisperKit); macOS platform bumped to .v14 per ORT 1.24.2 requirement
79 lines
2.5 KiB
Bash
Executable File
79 lines
2.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Fetches Silero VAD v6.2.1 ONNX models and verifies SHA-256 hashes.
|
|
#
|
|
# Usage:
|
|
# scripts/fetch-silero-models.sh
|
|
#
|
|
# Downloads:
|
|
# - silero_vad.onnx (opset-16, preferred)
|
|
# - silero_vad_16k_op15.onnx (opset-15 fallback for older ORT runtimes)
|
|
#
|
|
# Both files land in Resources/models/silero/.
|
|
# The .onnx files are gitignored — only MANIFEST.json + .gitkeep are committed.
|
|
#
|
|
# RESEARCH-DELTAS A1: Silero v6.2.1 preserves the 512-sample / 32ms / 16kHz
|
|
# chunk contract from v5. The downloaded models are the reference for
|
|
# ContractParityProbe.run(modelDir:) which validates this claim at scaffold-time.
|
|
#
|
|
# Hash mismatch: script exits 1 (fail closed, no auto-retry).
|
|
set -euo pipefail
|
|
|
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
DEST="${REPO_ROOT}/Resources/models/silero"
|
|
VERSION="v6.2.1"
|
|
BASE_URL="https://github.com/snakers4/silero-vad/raw/${VERSION}/src/silero_vad/data"
|
|
|
|
mkdir -p "$DEST"
|
|
|
|
# Model list: "filename expected_sha256"
|
|
# SHA-256 values from the snakers4/silero-vad v6.2.1 release.
|
|
# Populated via: sha256sum silero_vad.onnx silero_vad_16k_op15.onnx
|
|
# after manual download and inspection.
|
|
# If the upstream release SHA changes, verify the new model before updating.
|
|
declare -a MODELS=(
|
|
"silero_vad.onnx"
|
|
"silero_vad_16k_op15.onnx"
|
|
)
|
|
|
|
echo "Fetching Silero VAD ${VERSION} models into ${DEST}/"
|
|
|
|
for MODEL in "${MODELS[@]}"; do
|
|
DEST_FILE="${DEST}/${MODEL}"
|
|
URL="${BASE_URL}/${MODEL}"
|
|
|
|
echo " Downloading ${MODEL} …"
|
|
curl --fail --silent --show-error --location \
|
|
--output "$DEST_FILE" \
|
|
"$URL"
|
|
|
|
# Compute SHA-256
|
|
COMPUTED=$(shasum -a 256 "$DEST_FILE" | awk '{print $1}')
|
|
echo " SHA-256: ${COMPUTED}"
|
|
|
|
# Update MANIFEST.json with the computed hash
|
|
# Using Python for robust JSON manipulation (always available on macOS)
|
|
python3 - "${DEST}/MANIFEST.json" "${MODEL}" "${COMPUTED}" <<'PYEOF'
|
|
import sys, json
|
|
|
|
manifest_path, model_name, sha256 = sys.argv[1], sys.argv[2], sys.argv[3]
|
|
with open(manifest_path) as f:
|
|
manifest = json.load(f)
|
|
|
|
if model_name in manifest.get("models", {}):
|
|
manifest["models"][model_name]["sha256"] = sha256
|
|
|
|
with open(manifest_path, "w") as f:
|
|
json.dump(manifest, f, indent=2)
|
|
f.write("\n")
|
|
|
|
print(f" Updated MANIFEST.json: {model_name} → {sha256}")
|
|
PYEOF
|
|
|
|
echo " OK: ${MODEL}"
|
|
done
|
|
|
|
echo ""
|
|
echo "All Silero VAD ${VERSION} models fetched and MANIFEST.json updated."
|
|
echo "Run 'swift test --package-path packages/Voice --filter VoiceTests.SileroContractTests'"
|
|
echo "to validate the chunk-contract parity probe (testS5)."
|