- DB: paths table (contract #3) + helpers; patch_anchor (label/color) - API: GET /api/beats, POST /api/director (valid-empty degradation), /api/paths CRUD (validated POST -> 422), PATCH /api/anchors/{id}; manifest gains capsule:false (test_api.py key-set lock updated consciously) - CLI: features | direct | capsule subcommands -> lane stubs (exit-2 degradation) - Backend stubs with frozen contracts in docstrings: audio_features, director, capsule - Frontend: six lane stub modules imported from main.js; all phase-5 buttons pre-wired hidden in index.html; write-ui/body.capsule read-only mode; __F4D_API_BASE__ runtime override in state.js - Hooks (contract #6): transport.captureAudioStream/releaseAudioStream, scene3d.focusOn, scene3d.setHelpersVisible (+registerHelper; camPath gizmos) - Suite 121 -> 127 passed; npm build clean; live-browser verified (status file) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
26 lines
1.1 KiB
Python
26 lines
1.1 KiB
Python
"""Audio features: beats & onsets (spec M10, lane E). STUB — lane E fills the body.
|
|
|
|
Contract (frozen at foundation2 merge — phase-5 contract #1):
|
|
|
|
:func:`run_features` loads the **reference** video's ingest WAV (16 kHz mono from
|
|
``config.AUDIO_DIR``; the reference timeline *is* ``t_global``), runs beat/tempo tracking
|
|
and onset-strength detection (librosa is already a dependency), and writes
|
|
``config.BEATS_JSON``::
|
|
|
|
{"tempo_bpm": float | null,
|
|
"beats_s": [float, ...],
|
|
"onsets": [{"t_global_s": float, "strength": float 0..1}, ...],
|
|
"generated_by": "festival4d.audio_features"}
|
|
|
|
All times are ``t_global`` seconds. Quiet / short / beatless audio must produce a
|
|
*valid, empty* result (``tempo_bpm: null``, empty lists) — never a crash. Returns a
|
|
small summary dict for the CLI log. ``GET /api/beats`` serves the written file.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
def run_features() -> dict:
|
|
"""Analyze the reference soundtrack and write ``data/work/beats.json`` (see module doc)."""
|
|
raise NotImplementedError("audio features (lane E / M10)")
|