Skip to content

Latest commit

 

History

History
318 lines (261 loc) · 12.7 KB

File metadata and controls

318 lines (261 loc) · 12.7 KB

Contributing to Video Analytics

Thank you for your interest in contributing. This guide covers everything you need to set up a development environment, understand the codebase, and build the application.


Table of Contents


Architecture Overview

┌──────────────────────────────────────────────┐
│               Tauri v2 Shell                  │
│                 (Rust)                         │
│                                                │
│  ┌──────────────────────────────────────────┐  │
│  │          React Frontend (webview)         │  │
│  │                                           │  │
│  │   Components ──▶ Services ──▶ SQLite DB   │  │
│  │                                           │  │
│  │   React 19 + TypeScript                   │  │
│  │   React Query (server state)              │  │
│  │   Zustand (client state)                  │  │
│  └──────────────┬───────────────────────────┘  │
│                  │                               │
│                  │ Tauri Plugins                  │
│                  ▼                               │
│  ┌─────────────────────────────────────┐        │
│  │  tauri-plugin-sql    → SQLite DB    │        │
│  │  tauri-plugin-http   → External API │        │
│  │  tauri-plugin-dialog → File picker  │        │
│  │  tauri-plugin-fs     → File reads   │        │
│  └─────────────────────────────────────┘        │
└──────────────────────────────────────────────┘
                   │
                   │ External API (optional)
                   ▼
            ┌──────────────┐
            │  Agent.AI    │
            │  Webhook     │
            └──────────────┘

How it works: The React frontend calls TypeScript service functions directly (no HTTP layer). Services use the Tauri SQL plugin to read/write a local SQLite database. For LLM-powered Q&A extraction, the app calls the Agent.AI webhook via the Tauri HTTP plugin. Everything runs in-process — no sidecar, no server.


Processing Pipeline

When processing a meeting transcript, the app runs a 4-stage pipeline:

Stage Description
1. Parse Transcript Parse SRT/VTT file into timestamped segments
2. Q&A Extraction LLM-based (Agent.AI) or rule-based question-answer pair extraction
3. Keyword Extraction TF-IDF keyword/keyphrase extraction (custom TypeScript implementation)
4. Finalization Save results to database, update meeting status

Q&A Extraction logic (Stage 2):

  1. If Agent.AI is configured and monthly quota remains → send transcript to webhook
  2. If webhook fails or returns empty → fall back to rule-based extraction
  3. If no provider configured or quota exhausted → use rule-based extraction directly
  4. Usage counter increments only on successful LLM extraction

Tech Stack

Technology Version Purpose
Tauri 2 Desktop application framework (Rust)
React 19 UI framework
TypeScript 5 Type safety
TailwindCSS 4 Styling
React Router 7 Client-side routing
React Query 5 Data fetching + caching
Zustand 5 Client state management
Recharts 2 Dashboard charts
Lucide React latest Icons
Vite 6 Build tooling
SQLite Local database (via tauri-plugin-sql)

Project Structure

video-analytics/
├── README.md                    # Consumer-facing documentation
├── CONTRIBUTING.md              # This file (developer guide)
├── package.json                 # Dependencies & scripts
├── tsconfig.json                # TypeScript configuration
├── vite.config.ts               # Vite build configuration
├── index.html                   # SPA entry point
├── main.css                     # Global styles (Tailwind)
│
├── src/                         # ── React Frontend ──
│   ├── main.tsx                 # React entry point
│   ├── App.tsx                  # Root component + routes
│   │
│   ├── services/                # TypeScript service layer
│   │   ├── db.ts                #   Database singleton + init + migrations
│   │   ├── db-schema.ts         #   CREATE TABLE SQL + ALTER TABLE migrations
│   │   ├── srtParser.ts         #   SRT/VTT subtitle file parsing
│   │   ├── qaExtractor.ts       #   Rule-based Q&A extraction (regex + patterns)
│   │   ├── keywordExtractor.ts  #   Custom TF-IDF keyword extraction
│   │   ├── llmService.ts        #   Agent.AI webhook client (submit + poll)
│   │   ├── settingsService.ts   #   Settings CRUD + usage tracking
│   │   ├── meetingService.ts    #   Meeting CRUD + analytics
│   │   ├── courseService.ts     #   Course CRUD + relationships
│   │   ├── attendanceParser.ts  #   Zoom CSV attendance parsing
│   │   ├── exportService.ts     #   Data export (text/CSV)
│   │   ├── pipeline.ts          #   Processing orchestrator + progress callbacks
│   │   └── speakerMerger.ts     #   Speaker data transformation
│   │
│   ├── components/
│   │   ├── layout/
│   │   │   ├── AppShell.tsx     #   Main layout wrapper
│   │   │   ├── Header.tsx       #   Top navigation bar
│   │   │   └── Sidebar.tsx      #   Left nav + privacy toggle
│   │   ├── dashboard/
│   │   │   └── DashboardView.tsx#   Home dashboard with charts
│   │   ├── upload/
│   │   │   ├── UploadView.tsx   #   SRT/VTT upload form + usage counter
│   │   │   └── ProcessingProgress.tsx
│   │   ├── meetings/
│   │   │   ├── MeetingListView.tsx
│   │   │   └── MeetingDetailView.tsx  # Transcript, Q&A, keywords tabs
│   │   ├── courses/
│   │   │   ├── CourseListView.tsx
│   │   │   └── CourseDetailView.tsx   # Sessions, participants, attendance
│   │   ├── settings/
│   │   │   └── SettingsView.tsx #   LLM provider config
│   │   ├── analytics/           #   Analytics components
│   │   ├── keywords/            #   Keyword display components
│   │   ├── transcript/          #   Transcript display components
│   │   ├── common/              #   Shared components
│   │   └── ui/
│   │       └── Spinner.tsx
│   ├── hooks/
│   │   └── useProcessing.ts     #   Processing state management
│   ├── store/
│   │   └── appStore.ts          #   Zustand global store
│   ├── types/                   #   TypeScript type definitions
│   └── lib/
│       └── formatters.ts        #   Date/time/text formatters
│
├── src-tauri/                   # ── Tauri Desktop Shell ──
│   ├── Cargo.toml               # Rust dependencies
│   ├── tauri.conf.json          # Tauri app config (version, window, bundle)
│   ├── src/
│   │   ├── main.rs              #   App entry point
│   │   └── lib.rs               #   Plugin registration (SQL, HTTP, FS, dialog)
│   ├── capabilities/
│   │   └── default.json         #   Security permissions
│   └── icons/                   #   App icons (all platforms)
│
├── .github/
│   └── workflows/
│       └── build.yml            # CI/CD: 4-platform build + GitHub Release
│
└── scripts/
    ├── build-standalone.ps1     # Local portable build (Windows)
    └── kill-port.js             # Dev utility: kill process on port

Routes

Route Component Description
/ DashboardView Home dashboard with summary charts
/upload UploadView Upload SRT/VTT transcripts for processing
/meetings MeetingListView Browse all processed meetings
/meetings/:id MeetingDetailView Transcript, Q&A pairs, keywords tabs
/courses CourseListView Browse courses
/courses/:id CourseDetailView Sessions, participants, attendance matrix
/settings SettingsView LLM provider config, usage tracking

Database Schema

All data is stored in a local SQLite file managed by the Tauri SQL plugin.

Table Description
app_settings Single-row config: LLM provider, webhook URL, prompt, privacy, usage tracking
meetings Meeting metadata: title, date, file paths, processing status
transcript_segments Individual transcript segments with timestamps and speaker labels
qa_pairs Extracted question-answer pairs with speaker attribution
keywords Extracted keywords/keyphrases per meeting
courses Course metadata: name, description
course_sessions Links meetings to courses as sessions
attendance_records Parsed attendance data from Zoom CSV exports
session_attendance Maps attendance records to course sessions

Developer Setup

Prerequisites

  • Node.js 18+ and npm
  • Rust toolchain (install from https://rustup.rs)
  • Visual Studio Build Tools (Windows) or Xcode CLI (macOS) or build-essential (Linux)

Linux also requires:

sudo apt install libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf libgtk-3-dev libsoup-3.0-dev libjavascriptcoregtk-4.1-dev

Setup

  1. Clone the repo:

    git clone https://github.com/HCarbajales/video-analytics.git
    cd video-analytics
    git checkout free-tier
  2. Install dependencies:

    npm install
  3. Run the full desktop app:

    npm run tauri:dev

    This starts the Vite dev server + the Tauri window with hot reload.

  4. Or for frontend-only iteration (UI changes without recompiling Rust):

    npm run dev

Building

Local Build (Windows)

Build a portable zip locally using the PowerShell script:

npm run portable

Or directly:

powershell -ExecutionPolicy Bypass -File scripts\build-standalone.ps1

Output: release/VideoAnalytics-x.x.x-win-x64.zip

Local Build (any platform)

npm run tauri:build

Find the installer in src-tauri/target/release/bundle/.


Release Process

Releases are automated via GitHub Actions. The workflow builds for 4 platforms and creates a draft GitHub Release with installers and portable zips.

Steps

  1. Commit and push all changes to free-tier

  2. Create a version tag:

    git tag v0.7.0
    git push origin v0.7.0
  3. The v* tag push triggers .github/workflows/build.yml

  4. GitHub Actions builds 4 platform targets in parallel:

    Runner Target Outputs
    windows-latest x86_64-pc-windows-msvc NSIS installer + portable zip
    macos-latest aarch64-apple-darwin DMG + portable zip
    macos-13 x86_64-apple-darwin DMG + portable zip
    ubuntu-22.04 x86_64-unknown-linux-gnu DEB + AppImage + portable zip
  5. Once all builds complete, go to Releases on GitHub

  6. Review the draft release and click Publish

Version bumping

Before tagging a new release, update the version in:

  • src-tauri/tauri.conf.json"version"
  • package.json"version"

Keep these in sync with the git tag (e.g., all set to 0.7.0 for tag v0.7.0).

Re-tagging (if the build fails or you need to update)

git tag -d v0.7.0                      # delete local tag
git push origin :refs/tags/v0.7.0      # delete remote tag
# fix the issue, commit, push
git tag v0.7.0                         # re-create tag
git push origin v0.7.0                 # triggers workflow again