Skip to main content

FastHTML VAD alignment component for transcript decomposition with Silero VAD audio chunking, card stack navigation with audio playback, and Web Audio API integration.

Project description

cjm-transcript-vad-align

Install

pip install cjm_transcript_vad_align

Project Structure

nbs/
├── components/ (6)
│   ├── callbacks.ipynb          # Focus change callback and audio playback JavaScript for the alignment card stack
│   ├── card_stack_config.ipynb  # Card stack configuration, HTML IDs, and button IDs for the VAD alignment card stack
│   ├── helpers.ipynb            # State getters for the alignment step from InteractionContext
│   ├── keyboard_config.ipynb    # Alignment-specific keyboard building blocks for assembly into a shared ZoneManager
│   ├── step_renderer.ipynb      # Composable render functions for the alignment card stack column
│   └── vad_card.ipynb           # VAD chunk card renderer for the alignment card stack
├── routes/ (4)
│   ├── card_stack.ipynb  # Card stack operations for the alignment column: navigation, viewport update, width save
│   ├── core.ipynb        # Alignment state context, getters, and updaters for route handlers
│   ├── handlers.ipynb    # Workflow-specific alignment handlers: init
│   └── init.ipynb        # Router assembly for Phase 2 alignment routes
├── services/ (1)
│   └── alignment.ipynb  # Alignment service for temporal coordination via Silero VAD plugin
├── html_ids.ipynb  # HTML ID constants for Phase 2 Right Column: VAD Alignment
├── models.ipynb    # Data models and URL bundles for the alignment package
└── utils.ipynb     # Time formatting utilities for VAD alignment display

Total: 14 notebooks across 3 directories

Module Dependencies

graph LR
    components_callbacks[components.callbacks<br/>callbacks]
    components_card_stack_config[components.card_stack_config<br/>card_stack_config]
    components_helpers[components.helpers<br/>helpers]
    components_keyboard_config[components.keyboard_config<br/>keyboard_config]
    components_step_renderer[components.step_renderer<br/>step_renderer]
    components_vad_card[components.vad_card<br/>vad_card]
    html_ids[html_ids<br/>html_ids]
    models[models<br/>models]
    routes_card_stack[routes.card_stack<br/>card_stack]
    routes_core[routes.core<br/>core]
    routes_handlers[routes.handlers<br/>handlers]
    routes_init[routes.init<br/>init]
    services_alignment[services.alignment<br/>alignment]
    utils[utils<br/>utils]

    components_helpers --> models
    components_step_renderer --> components_card_stack_config
    components_step_renderer --> models
    components_step_renderer --> components_vad_card
    components_step_renderer --> components_callbacks
    components_step_renderer --> html_ids
    components_vad_card --> models
    components_vad_card --> utils
    components_vad_card --> html_ids
    routes_card_stack --> components_card_stack_config
    routes_card_stack --> routes_core
    routes_card_stack --> components_vad_card
    routes_card_stack --> models
    routes_core --> models
    routes_handlers --> models
    routes_handlers --> components_step_renderer
    routes_handlers --> routes_core
    routes_handlers --> html_ids
    routes_handlers --> services_alignment
    routes_init --> routes_core
    routes_init --> routes_handlers
    routes_init --> routes_card_stack
    routes_init --> services_alignment
    routes_init --> models
    services_alignment --> models

25 cross-module dependencies detected

CLI Reference

No CLI commands found in this project.

Module Overview

Detailed documentation for each module in the project:

alignment (alignment.ipynb)

Alignment service for temporal coordination via Silero VAD plugin

Import

from cjm_transcript_vad_align.services.alignment import (
    AlignmentService,
    check_alignment_ready
)

Functions

def check_alignment_ready(
    segment_count: int,  # Number of text segments
    chunk_count: int,  # Number of VAD chunks
) -> bool:  # True if counts match and alignment can proceed
    "Check if segment and VAD chunk counts match for 1:1 alignment."

Classes

class AlignmentService:
    def __init__(
        self,
        plugin_manager: PluginManager,  # Plugin manager for accessing VAD plugin
        plugin_name: str = "cjm-media-plugin-silero-vad"  # Name of the VAD plugin
    )
    "Service for temporal alignment via Silero VAD plugin."
    
    def __init__(
            self,
            plugin_manager: PluginManager,  # Plugin manager for accessing VAD plugin
            plugin_name: str = "cjm-media-plugin-silero-vad"  # Name of the VAD plugin
        )
        "Initialize the alignment service."
    
    def is_available(self) -> bool:  # True if plugin is loaded and ready
            """Check if the VAD plugin is available."""
            return self._manager.get_plugin(self._plugin_name) is not None
        
        def ensure_loaded(
            self,
            config: Optional[Dict[str, Any]] = None  # Optional plugin configuration
        ) -> bool:  # True if successfully loaded
        "Check if the VAD plugin is available."
    
    def ensure_loaded(
            self,
            config: Optional[Dict[str, Any]] = None  # Optional plugin configuration
        ) -> bool:  # True if successfully loaded
        "Ensure the VAD plugin is loaded."
    
    async def analyze_audio_async(
            self,
            media_path: str  # Path to audio/video file
        ) -> tuple[List[VADChunk], float]:  # (VAD chunks, total duration)
        "Analyze audio file and return VAD chunks."
    
    def analyze_audio(
            self,
            media_path: str  # Path to audio/video file
        ) -> tuple[List[VADChunk], float]:  # (VAD chunks, total duration)
        "Analyze audio file synchronously."

callbacks (callbacks.ipynb)

Focus change callback and audio playback JavaScript for the alignment card stack

Import

from cjm_transcript_vad_align.components.callbacks import (
    generate_align_callbacks_script
)

Functions

def _generate_align_focus_change_script(
    focus_input_id:str,  # ID of hidden input for focused chunk index
    audio_player_id:str,  # ID of the hidden audio element (for src URL extraction)
    card_stack_id:str,  # ID of the alignment card stack container
) -> str:  # JavaScript for focus change with audio playback and playing indicator
    "Generate JS for VAD chunk focus change handling with Web Audio API playback."
def generate_align_callbacks_script(
    ids:CardStackHtmlIds,  # Card stack HTML IDs
    button_ids:CardStackButtonIds,  # Card stack button IDs
    config:CardStackConfig,  # Card stack configuration
    urls:CardStackUrls,  # Card stack URL bundle
    container_id:str,  # ID of the alignment container (parent of card stack)
    focus_input_id:str,  # ID of hidden input for focused chunk index
    audio_player_id:str,  # ID of the hidden audio element
) -> any:  # Script element with all JavaScript callbacks
    "Generate JavaScript for alignment card stack with audio audition."

card_stack (card_stack.ipynb)

Card stack operations for the alignment column: navigation, viewport update, width save

Import

from cjm_transcript_vad_align.routes.card_stack import (
    init_card_stack_router
)

Functions

def _build_nav_response(
    chunk_dicts:List[Dict[str, Any]],  # Serialized VAD chunks
    state:CardStackState,  # Current card stack state
    urls:AlignmentUrls,  # URL bundle
) -> Tuple:  # OOB response elements (slots + progress + focus)
    "Build OOB response for navigation changes."
def _handle_align_navigate(
    state_store:WorkflowStateStore,  # The workflow state store
    workflow_id:str,  # The workflow identifier
    sess:Any,  # FastHTML session object
    direction:str,  # Navigation direction: up/down/first/last/page_up/page_down
    urls:AlignmentUrls,  # URL bundle
) -> Tuple:  # OOB response elements (slots + progress + focus)
    "Navigate the alignment card stack."
async def _handle_align_update_viewport(
    state_store:WorkflowStateStore,  # The workflow state store
    workflow_id:str,  # The workflow identifier
    request:Any,  # FastHTML request object
    sess:Any,  # FastHTML session object
    visible_count:int,  # New visible card count
    urls:AlignmentUrls,  # URL bundle
) -> Tuple:  # OOB section elements for viewport update
    "Update viewport with new card count via OOB section swaps."
def _handle_align_save_width(
    state_store:WorkflowStateStore,  # The workflow state store
    workflow_id:str,  # The workflow identifier
    sess:Any,  # FastHTML session object
    card_width:int,  # Card stack width in rem to save
) -> None:  # No response body (swap=none on client)
    "Save card stack width to server state with config bounds validation."
def init_card_stack_router(
    state_store:WorkflowStateStore,  # The workflow state store
    workflow_id:str,  # The workflow identifier
    prefix:str,  # Route prefix (e.g., "/workflow/align/card_stack")
    urls:AlignmentUrls,  # URL bundle (populated after routes defined)
) -> Tuple[APIRouter, Dict[str, Callable]]:  # (router, route_dict)
    "Initialize card stack routes for alignment."

card_stack_config (card_stack_config.ipynb)

Card stack configuration, HTML IDs, and button IDs for the VAD alignment card stack

Import

from cjm_transcript_vad_align.components.card_stack_config import (
    ALIGN_CS_CONFIG,
    ALIGN_CS_IDS,
    ALIGN_CS_BTN_IDS
)

Variables

ALIGN_CS_CONFIG
ALIGN_CS_IDS
ALIGN_CS_BTN_IDS

core (core.ipynb)

Alignment state context, getters, and updaters for route handlers

Import

from cjm_transcript_vad_align.routes.core import (
    WorkflowStateStore,
    DEBUG_ALIGN_STATE,
    AlignContext
)

Functions

def _get_alignment_state(
    state_store:WorkflowStateStore,  # The workflow state store
    workflow_id:str,  # The workflow identifier
    session_id:str,  # Session identifier
) -> AlignmentStepState:  # Typed alignment step state
    "Get the alignment step state from the workflow state store."
def _get_selection_state(
    state_store:WorkflowStateStore,  # The workflow state store
    workflow_id:str,  # The workflow identifier
    session_id:str,  # Session identifier
) -> Dict[str, Any]:  # Selection step state dictionary
    "Get the selection step state (Phase 1) from the workflow state store."
def _load_alignment_context(
    state_store:WorkflowStateStore,  # The workflow state store
    workflow_id:str,  # The workflow identifier
    session_id:str,  # Session identifier
) -> AlignContext:  # Loaded context with all common alignment state
    "Load commonly-needed alignment state values in a single call."
def _update_alignment_state(
    state_store:WorkflowStateStore,  # The workflow state store
    workflow_id:str,  # The workflow identifier
    session_id:str,  # Session identifier
    vad_chunks=None,  # Updated VAD chunks (serialized)
    focused_chunk_index=None,  # Updated focused chunk index
    is_initialized=None,  # Initialization flag
    visible_count=None,  # Visible card count
    is_auto_mode=None,  # Auto-adjust mode flag
    card_width=None,  # Card stack width in rem
    media_path=None,  # Original audio file path
    audio_duration=None,  # Audio duration
) -> None
    "Update the alignment step state in the workflow state store."
def _to_vad_chunks(
    chunk_dicts:List[Dict[str, Any]]  # Serialized VAD chunk dictionaries
) -> List[VADChunk]:  # List of VADChunk objects
    "Convert chunk dictionaries to VADChunk objects."
def _build_card_stack_state(
    ctx:AlignContext,  # Loaded alignment context
    active_mode:str=None,  # Current interaction mode name (unused for alignment)
) -> CardStackState:  # Card stack state for library functions
    "Build a CardStackState from alignment context for library functions."

Classes

class AlignContext(NamedTuple):
    "Common alignment state values loaded by handlers."

Variables

DEBUG_ALIGN_STATE = False

handlers (handlers.ipynb)

Workflow-specific alignment handlers: init

Import

from cjm_transcript_vad_align.routes.handlers import (
    DEBUG_ALIGNMENT,
    AlignInitResult,
    init_workflow_router
)

Functions

async def _handle_align_init(
    state_store:WorkflowStateStore,  # The workflow state store
    workflow_id:str,  # The workflow identifier
    source_service:SourceService,  # Service for fetching source blocks
    alignment_service:AlignmentService,  # Service for VAD analysis
    request,  # FastHTML request object
    sess,  # FastHTML session object
    urls:AlignmentUrls,  # URL bundle
    visible_count:int=DEFAULT_VISIBLE_COUNT,  # Initial visible card count
    card_width:int=DEFAULT_CARD_WIDTH,  # Initial card width in rem
) -> AlignInitResult:  # Pure domain result for wrapper to use
    """
    Initialize alignment from audio file via VAD plugin.
    
    Returns pure domain data. The combined layer wrapper adds cross-domain
    coordination (shared chrome, alignment status).
    """
def init_workflow_router(
    state_store:WorkflowStateStore,  # The workflow state store
    workflow_id:str,  # The workflow identifier
    source_service:SourceService,  # Service for fetching source blocks
    alignment_service:AlignmentService,  # Service for VAD analysis
    prefix:str,  # Route prefix (e.g., "/workflow/align/workflow")
    urls:AlignmentUrls,  # URL bundle (populated after routes defined)
    handler_init:Callable=None,  # Optional wrapped init handler
) -> Tuple[APIRouter, Dict[str, Callable]]:  # (router, route_dict)
    """
    Initialize workflow routes for alignment.
    
    Accepts optional handler override for wrapping with cross-domain
    coordination (e.g., shared chrome, alignment status OOB updates).
    """

Classes

class AlignInitResult(NamedTuple):
    """
    Result from pure alignment init handler.
    
    Contains domain-specific data for the combined layer wrapper to use
    when building cross-domain OOB elements (shared chrome, alignment status).
    """

Variables

DEBUG_ALIGNMENT = True

helpers (helpers.ipynb)

State getters for the alignment step from InteractionContext

Import

from cjm_transcript_vad_align.components.helpers import *

Functions

def _get_alignment_state(
    ctx:InteractionContext  # Interaction context with state
) -> AlignmentStepState:  # Typed alignment step state
    "Get the full alignment step state from context."
def _get_vad_chunks(
    ctx:InteractionContext  # Interaction context with state
) -> List[VADChunk]:  # List of VADChunk objects
    "Get the list of VAD chunks from step state as VADChunk objects."
def _is_alignment_initialized(
    ctx:InteractionContext  # Interaction context with state
) -> bool:  # True if VAD data has been fetched
    "Check if alignment has been initialized."
def _get_focused_chunk_index(
    ctx:InteractionContext,  # Interaction context with state
    default:int=0,  # Default focused chunk index
) -> int:  # Currently focused VAD chunk index
    "Get the currently focused VAD chunk index."
def _get_alignment_visible_count(
    ctx:InteractionContext,  # Interaction context with state
    default:int=5,  # Default visible card count (compact cards)
) -> int:  # Number of visible cards in viewport
    "Get the stored visible card count."
def _get_alignment_is_auto_mode(
    ctx:InteractionContext,  # Interaction context with state
) -> bool:  # Whether card count is in auto-adjust mode
    "Get whether the card count is in auto-adjust mode."
def _get_alignment_card_width(
    ctx:InteractionContext,  # Interaction context with state
    default:int=40,  # Default card width in rem (narrower for alignment)
) -> int:  # Card stack width in rem
    "Get the stored card stack width."
def _get_alignment_history(
    ctx:InteractionContext  # Interaction context with state
) -> list:  # Undo history stack
    "Get the undo history stack."
def _get_media_path(
    ctx:InteractionContext  # Interaction context with state
) -> Optional[str]:  # Path to original audio file or None
    "Get the original audio file path."
def _get_audio_duration(
    ctx:InteractionContext  # Interaction context with state
) -> Optional[float]:  # Audio duration in seconds or None
    "Get the total audio duration."

html_ids (html_ids.ipynb)

HTML ID constants for Phase 2 Right Column: VAD Alignment

Import

from cjm_transcript_vad_align.html_ids import (
    AlignmentHtmlIds
)

Classes

class AlignmentHtmlIds:
    "HTML ID constants for Phase 2 Right Column: VAD Alignment."
    
    def as_selector(
            id_str:str  # The HTML ID to convert
        ) -> str:  # CSS selector with # prefix
        "Convert an ID to a CSS selector format."
    
    def vad_chunk(
            index:int  # VAD chunk index
        ) -> str:  # HTML ID for the VAD chunk element
        "Generate HTML ID for a VAD chunk element."

init (init.ipynb)

Router assembly for Phase 2 alignment routes

Import

from cjm_transcript_vad_align.routes.init import (
    init_alignment_routers
)

Functions

def init_alignment_routers(
    state_store:WorkflowStateStore,  # The workflow state store
    workflow_id:str,  # The workflow identifier
    source_service:SourceService,  # Service for fetching source blocks
    alignment_service:AlignmentService,  # Service for VAD analysis
    prefix:str,  # Base prefix for alignment routes (e.g., "/workflow/align")
    audio_src_url:str,  # URL for audio_src route (from core router)
    wrapped_init:Callable=None,  # Optional wrapped init handler
) -> Tuple[List[APIRouter], AlignmentUrls, Dict[str, Callable]]:  # (routers, urls, merged_routes)
    "Initialize and return all alignment routers with URL bundle."

keyboard_config (keyboard_config.ipynb)

Alignment-specific keyboard building blocks for assembly into a shared ZoneManager

Import

from cjm_transcript_vad_align.components.keyboard_config import (
    create_align_kb_parts
)

Functions

def create_align_kb_parts(
    ids:CardStackHtmlIds,  # Card stack HTML IDs
    button_ids:CardStackButtonIds,  # Card stack button IDs for navigation
    config:CardStackConfig,  # Card stack configuration
) -> Tuple[FocusZone, tuple, tuple]:  # (zone, actions, modes)
    "Create alignment-specific keyboard building blocks."

models (models.ipynb)

Data models and URL bundles for the alignment package

Import

from cjm_transcript_vad_align.models import (
    AlignmentStepState,
    VADChunk,
    AlignmentUrls
)

Classes

class AlignmentStepState(TypedDict):
    "State for Phase 2 (right column): Temporal Alignment."
@dataclass
class VADChunk:
    "A voice activity detection time range."
    
    index: int  # Chunk index in sequence
    start_time: float  # Start time in seconds
    end_time: float  # End time in seconds
    
    def duration(self) -> float:  # Duration in seconds
            """Calculate chunk duration."""
            return self.end_time - self.start_time
        
        def to_dict(self) -> Dict[str, Any]:  # Dictionary representation
        "Calculate chunk duration."
    
    def to_dict(self) -> Dict[str, Any]:  # Dictionary representation
            """Convert to dictionary for JSON serialization."""
            return asdict(self)
        
        @classmethod
        def from_dict(
            cls,
            data: Dict[str, Any]  # Dictionary representation
        ) -> "VADChunk":  # Reconstructed VADChunk
        "Convert to dictionary for JSON serialization."
    
    def from_dict(
            cls,
            data: Dict[str, Any]  # Dictionary representation
        ) -> "VADChunk":  # Reconstructed VADChunk
        "Create from dictionary."
@dataclass
class AlignmentUrls:
    "URL bundle for Phase 2 alignment route handlers and renderers."
    
    card_stack: CardStackUrls = field(...)
    init: str = ''  # Initialize alignment (fetch VAD data)
    audio_src: str = ''  # Audio file serving URL base

step_renderer (step_renderer.ipynb)

Composable render functions for the alignment card stack column

Import

from cjm_transcript_vad_align.components.step_renderer import (
    DEBUG_ALIGN_RENDER,
    render_align_toolbar,
    render_align_stats,
    render_align_column_body,
    render_align_footer_content,
    render_align_mini_stats_text
)

Functions

def render_align_toolbar(
    visible_count:int=DEFAULT_VISIBLE_COUNT,  # Current visible card count
    is_auto_mode:bool=False,  # Whether card count is in auto-adjust mode
    oob:bool=False,  # Whether to render as OOB swap
) -> Any:  # Toolbar component
    "Render the alignment toolbar with card count selector."
def render_align_stats(
    chunks:List[VADChunk],  # Current VAD chunks
    oob:bool=False,  # Whether to render as OOB swap
) -> Any:  # Statistics component
    "Render alignment statistics."
def render_align_column_body(
    chunks:List[VADChunk],  # VAD chunks to display
    focused_index:int,  # Currently focused chunk index
    visible_count:int,  # Number of visible cards in viewport
    card_width:int,  # Card stack width in rem
    urls:AlignmentUrls,  # URL bundle for alignment routes
    kb_system:Any=None,  # Rendered keyboard system (None when KB managed externally)
    media_path:Optional[str]=None,  # Path to audio file for playback
) -> Any:  # Div with id=COLUMN_CONTENT
    "Render the alignment column content area with card stack viewport."
def render_align_footer_content(
    chunks:List[VADChunk],  # Current VAD chunks
    focused_index:int,  # Currently focused chunk index
) -> Any:  # Footer content with progress indicator and stats
    "Render footer content with progress indicator and alignment statistics."
def render_align_mini_stats_text(
    chunks:List[VADChunk],  # Current VAD chunks
) -> str:  # Compact stats string for column header badge
    "Generate compact stats string for the alignment column header badge."

Variables

DEBUG_ALIGN_RENDER = False

utils (utils.ipynb)

Time formatting utilities for VAD alignment display

Import

from cjm_transcript_vad_align.utils import (
    format_time_precise
)

Functions

def format_time_precise(
    seconds: Optional[float]  # Time in seconds
) -> str:  # Formatted time string (m:ss.s)
    "Format seconds as m:ss.s for sub-second display."

vad_card (vad_card.ipynb)

VAD chunk card renderer for the alignment card stack

Import

from cjm_transcript_vad_align.components.vad_card import (
    render_vad_card,
    create_vad_card_renderer
)

Functions

def render_vad_card(
    chunk:VADChunk,  # VAD chunk to render
    card_role:CardRole,  # Role of this card in viewport ("focused" or "context")
) -> Any:  # VAD chunk card component
    "Render a single VAD chunk card with time range, duration, and playing indicator."
def create_vad_card_renderer() -> Callable:  # Card renderer callback: (item, CardRenderContext) -> FT
    """Create a card renderer callback for VAD chunk cards."""
    def _render(
        item:Any,  # VADChunk instance
        context:CardRenderContext,  # Render context from card stack library
    ) -> Any:  # Rendered VAD chunk card component
    "Create a card renderer callback for VAD chunk cards."

Project details


Download files

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

Source Distribution

cjm_transcript_vad_align-0.0.1.tar.gz (34.5 kB view details)

Uploaded Source

Built Distribution

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

cjm_transcript_vad_align-0.0.1-py3-none-any.whl (36.2 kB view details)

Uploaded Python 3

File details

Details for the file cjm_transcript_vad_align-0.0.1.tar.gz.

File metadata

  • Download URL: cjm_transcript_vad_align-0.0.1.tar.gz
  • Upload date:
  • Size: 34.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for cjm_transcript_vad_align-0.0.1.tar.gz
Algorithm Hash digest
SHA256 45820772732092039297314f58d939c13bbe7fb742253cdb6f62abed46d3d4c2
MD5 9bd30d1fd0559be38dd729b9e962724e
BLAKE2b-256 0bbe03f1714368e734b883dd802e1bea72d9332e1b0876b868de76e6e847a8ef

See more details on using hashes here.

File details

Details for the file cjm_transcript_vad_align-0.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for cjm_transcript_vad_align-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 4b7ce2dd4ca0612ff50004396f29788524b850dbddd4c424b846d1439b3f4d13
MD5 369453393ed9948c7b125e5e5d200390
BLAKE2b-256 855f1d984cde2371163ee317cb0f479ad360598e52135e4eab95d163aeefa175

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page