diff --git a/README.md b/README.md index b2c6386..092853f 100644 --- a/README.md +++ b/README.md @@ -10,33 +10,125 @@ ![Node.js 20+](https://img.shields.io/badge/Node.js-20%2B-339933) ![Developer beta](https://img.shields.io/badge/status-developer%20beta-f59e0b) -Web Video Optimizer is a local-first browser app for turning source videos into website-ready assets. It uploads media to your own machine, runs FFmpeg locally, compares output quality in the browser, and builds a clean website package with modern and fallback video files, poster artwork, captions, transcript markup, and SEO-friendly embed code. +Web Video Optimizer is a local-first browser workspace for turning source videos into website-ready media packages. It runs FFmpeg on your computer, creates compatible and modern video outputs, lets you compare visual quality, and packages video, poster, caption, transcript, embed, and structured-data assets for deployment. + +It is intended for web developers, content teams, marketers, and creators who need deployable web video assets without sending source media to a hosted conversion service. In the default local configuration, the browser sends media to the local WVO API process and the API keeps sources and generated files on your machine. - Web Video Optimizer results workspace showing optimized outputs and package controls + Results workspace showing completed outputs, package readiness, and selected output details -## Status +## Contents + +- [Status And Scope](#status-and-scope) +- [Why WVO Exists](#why-wvo-exists) +- [Plain-English Tour](#plain-english-tour) +- [Key Capabilities](#key-capabilities) +- [Quick Start](#quick-start) +- [Workflow](#workflow) +- [Architecture At A Glance](#architecture-at-a-glance) +- [Processing Sequence](#processing-sequence) +- [What WVO Creates](#what-wvo-creates) +- [Optimization Workflows](#optimization-workflows) +- [Review And Comparison](#review-and-comparison) +- [Captions, Posters, And Packages](#captions-posters-and-packages) +- [Persistence And Managed Storage](#persistence-and-managed-storage) +- [Repository Layout](#repository-layout) +- [Development Commands](#development-commands) +- [Gallery](#gallery) +- [Privacy And Security](#privacy-and-security) +- [Current Limitations](#current-limitations) +- [Documentation Map](#documentation-map) +- [Contributing And License](#contributing-and-license) + +## Status And Scope This project is a developer beta. The core local workflow is usable and tested, but the app is intentionally focused on trusted local or LAN use rather than public hosting. There are no accounts, cloud media uploads, analytics, or hosted processing services. -## Why +| Area | Current state | +| ------------------------- | -------------------------------- | +| Local upload and probing | Available | +| Recommended MP4/WebM pair | Available | +| Browser comparison | Available | +| Posters and packages | Available | +| Caption generation | Optional local dependency | +| YouTube import | Optional local dependency | +| Public hosted deployment | Not the supported security model | +| Accounts/cloud sync | Not included | + +## Why WVO Exists + +Preparing video for the web usually means juggling codec settings, fallback files, posters, captions, embed markup, file sizes, browser preview checks, and structured data. A generic transcoder can convert a file, but it usually does not guide the whole website handoff. + +WVO is workflow-oriented rather than codec-only. It combines compatibility exports, modern compression, WebP poster generation, optional captions, transcript markup, structured data, browser comparison, persistent history, and a local browser interface around FFmpeg and FFprobe. + +## Plain-English Tour + +1. Add a local source or supported URL. Upload a file in the browser, drag one into the drop zone, or import a supported YouTube URL when yt-dlp is configured. +2. Review metadata and web-compatibility information. WVO shows dimensions, duration, size, codecs, audio status, subtitle tracks, and compatibility status. +3. Run the recommended website optimization. The main workflow creates a compatible H.264 MP4 fallback and a modern WebM/AV1 output. +4. Watch queued and running jobs. Jobs are scheduled through the local API, report progress, and can be canceled. +5. Compare source and outputs. Use synchronized playback to inspect quality and browser support at the same timestamp. +6. Create a poster and captions. Generate a WebP poster and, when whisper.cpp is configured, generate and edit captions. +7. Assemble the website package. Select completed outputs, poster, and captions, then add package metadata. +8. Download the ZIP and embed assets. The package includes deployable media plus `embed.html` and `README.txt`. +9. Reopen earlier sources from the Library. History is restored from the local manifest across refreshes and API restarts. + +## Key Capabilities + +**Source preparation** + +- Local video upload. +- Optional supported YouTube URL import through yt-dlp. +- Metadata and codec inspection through FFprobe. +- Source renaming. +- Web-compatibility status. -Preparing video for the web usually means juggling codec settings, fallback files, posters, captions, embed markup, file sizes, and browser preview checks. This app gives that work a single local workspace: +**Optimization** -- Import a local file or a supported YouTube URL. -- Inspect metadata before encoding. -- Create a compatible H.264 MP4 and a smaller modern WebM/AV1 output. -- Preview, compare, rename, cancel, delete, and download outputs. -- Generate poster images, captions, transcript markup, and a website ZIP. -- Keep previous sources and jobs available between browser refreshes and API restarts. +- Recommended compatible MP4 fallback and modern WebM output. +- Custom export controls for container, codec, dimensions, frame rate, quality, audio, and output name. +- Bounded media job scheduling. +- Cancelation and progress reporting. + +**Review** + +- Browser playback from local byte-range streams. +- Grid comparison with 1-up, 2-up, 4-up, and auto layouts. +- Wipe and A/B comparison modes. +- Synchronized comparison playback. +- Output size and savings presentation. + +**Delivery** + +- WebP poster generation. +- VTT and SRT caption sidecars when captions are generated. +- Caption editing and preview. +- Transcript markup. +- Embed code with `VideoObject` JSON-LD. +- Website ZIP package. + +**Persistence and operations** + +- History restoration from `manifest.json`. +- Managed storage cleanup. +- Startup recovery for interrupted work. +- Local health and readiness checks. ## Quick Start -### Local Node +### Prerequisites -Local development needs Node.js 20 or newer and FFmpeg/FFprobe on PATH. +- Node.js 20 or newer. +- npm. +- FFmpeg and FFprobe on PATH. +- A supported modern browser. +- Optional: Docker. +- Optional: yt-dlp for YouTube import. +- Optional: whisper.cpp and a local model for caption generation. + +### Local Node ```powershell git clone https://github.com/Artsen/web-video-optimizer.git @@ -45,11 +137,24 @@ npm ci npm run dev ``` -Open . The API listens on and must remain running while the web interface is used. +Expected services: -On Windows PowerShell, use `npm.cmd` if script execution policy blocks `npm.ps1`. +```text +Web interface: http://127.0.0.1:5173 +Local API: http://127.0.0.1:4000 +Health: http://127.0.0.1:4000/health +Readiness: http://127.0.0.1:4000/ready +``` + +`npm run dev` builds shared packages, starts the API, starts the Vite application, streams both services into one terminal, shuts down the sibling process when one exits, and terminates both process trees on `Ctrl+C`. The launcher includes Windows-specific process-tree handling. -The two-console workflow is still supported: +On Windows PowerShell, use `npm.cmd` if script execution policy blocks `npm.ps1`: + +```powershell +npm.cmd run dev +``` + +### Separate Dev Consoles ```powershell npm run dev:api @@ -75,68 +180,216 @@ See [Getting Started](docs/getting-started.md) for FFmpeg setup, LAN access, yt- ```mermaid flowchart LR - A[Add source video] --> B[Inspect metadata] + A[Add source] --> B[Probe and inspect] B --> C[Optimize for website] C --> D[Review outputs] D --> E[Compare quality] D --> F[Generate poster] - D --> G[Create captions] - F --> H[Build website package] + D --> G[Create or edit captions] + E --> H[Choose deliverables] + F --> H G --> H - H --> I[Download ZIP and embed code] + H --> I[Build website package] + I --> J[Download ZIP and embed assets] + + D -. optional .-> K[Custom export] + K --> D +``` + +## Architecture At A Glance + +```mermaid +flowchart LR + Browser[React browser app] + API[Local Express API] + Contracts[Shared contracts] + Core[video-core] + Storage[(Managed local storage)] + FFmpeg[FFmpeg / FFprobe] + Whisper[Optional whisper.cpp] + YtDlp[Optional yt-dlp] + + Browser -->|uploads, JSON, SSE, byte ranges| API + API --> Contracts + API --> Core + API --> Storage + API --> FFmpeg + API -. optional .-> Whisper + API -. optional .-> YtDlp +``` + +The browser app owns the workspace, route state, comparison UI, and package controls. The local API owns validation, storage boundaries, FFmpeg/FFprobe work, optional tool adapters, job scheduling, history, and downloads. + +Shared contracts keep request and response shapes consistent between the API and web app. See [Architecture](docs/architecture.md) for the full service and storage model. + +## Processing Sequence + +```mermaid +sequenceDiagram + actor User + participant Web as Browser UI + participant API as Local API + participant Store as Managed storage + participant Media as FFmpeg / FFprobe + + User->>Web: Add source video + Web->>API: Upload source + API->>Store: Stage and save source + API->>Media: Probe metadata + Media-->>API: Metadata and capabilities + API-->>Web: Source record + User->>Web: Optimize for website + Web->>API: Create paired jobs + API->>Media: Run bounded encodes + API->>Store: Save completed outputs + API-->>Web: Stream progress and results ``` -## What It Creates +## What WVO Creates + +The recommended website workflow creates two video outputs: - `*-fallback-h264.mp4` for broad browser compatibility. - `*-modern-av1.webm` for modern compression. -- `*-poster.webp` poster artwork. -- `.vtt` and `.srt` caption sidecars when subtitles are generated. -- Optional subtitle-remuxed MP4/WebM outputs. -- A ZIP package with media assets, transcript markup, and `VideoObject` structured data. -## Gallery +Package ZIP contents depend on which completed jobs are selected. A typical package with videos, poster, and captions contains: + +```text +example-web-package.zip +|-- example-fallback-h264.mp4 +|-- example-modern-av1.webm +|-- example-poster.webp +|-- example-captions.vtt +|-- example-captions.srt +|-- example-transcript.txt +|-- embed.html +`-- README.txt +``` + +| Asset | Role | +| ----------------------------- | ----------------------------------------------------------------------------- | +| Fallback video | Broad browser playback path, usually H.264 MP4. | +| Modern video | Smaller modern-browser source, usually AV1 WebM. | +| Poster | WebP poster used before playback. | +| Captions | VTT for web playback and SRT sidecar for compatibility. | +| Transcript | Plain-text transcript extracted from captions. | +| `embed.html` | Preview page and production embed snippet. | +| `VideoObject` structured data | JSON-LD included in the generated embed markup. | +| `README.txt` | Package notes, selected files, accessibility notes, and publishing reminders. | + +## Optimization Workflows + +| Workflow | Best for | +| -------------------- | ----------------------------------------------------------------------------------------------- | +| Optimize for website | Fast default path producing the recommended compatible and modern pair. | +| Custom Export | Manually controlling codec, container, dimensions, frame rate, quality, audio, and output name. | + +The default path is for ordinary website delivery. Custom Export is for source-specific constraints, special codec experiments, silent hero video, or alternate naming. + +## Review And Comparison + +The Compare workspace is a theatre-style review surface for checking visual quality, size, and browser playback at the same timestamp. + +| Mode | Useful for | +| ---- | ---------------------------------------------------------------------------------------- | +| Grid | Seeing the source and up to three outputs together in auto, 1-up, 2-up, or 4-up layouts. | +| Wipe | Dragging a center divider between the original and a selected output. | +| A/B | Switching between original and output with matching playback state. | + +Comparison supports synchronized play/pause, seeking, playback rate, loop, audio-source selection, frame stepping while paused, linked zoom, pan, and fullscreen. The URL restores selected output, mode, layout, and visible versions. Playback time, volume, zoom, pan, wipe percentage, and fullscreen are intentionally temporary review state. + +See the [User Guide](docs/user-guide.md) for the full workflow. + +## Captions, Posters, And Packages + +FFprobe detects embedded subtitle tracks during source inspection. If no subtitle track exists and the source has audio, WVO can generate captions with local whisper.cpp when `WHISPER_CPP_BIN` and `WHISPER_CPP_MODEL` are configured. + +Generated captions can be previewed over video, edited in the caption theatre, downloaded as `.vtt` and `.srt`, included in the ZIP package, or remuxed into completed MP4/WebM outputs. + +Poster generation creates a WebP image from the current source. Package assembly combines selected completed jobs with title, description, language, and filename-prefix metadata. + +## Persistence And Managed Storage + +Sources and jobs are retained through `manifest.json`. Managed storage is separated into uploads, outputs, temporary work, and upload staging. Completed work can be reopened from the Library after browser refreshes and API restarts. -| Prepare | Results | Compare | -| --------------------------------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------ | -| ![Prepare workspace](docs/assets/screenshots/prepare-dark.webp) | ![Results workspace](docs/assets/screenshots/results-dark.webp) | ![Compare theatre](docs/assets/screenshots/compare-wipe-dark.webp) | +On startup, the API reconciles interrupted work, restores completed jobs with existing outputs, skips dangling entries, handles duplicates, and cleans eligible temporary or orphaned data. See [Architecture](docs/architecture.md) and [Configuration](docs/configuration.md) for storage details. -| Custom Export | Mobile | -| -------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | -| ![Custom export controls](docs/assets/screenshots/custom-export-dark.webp) | ![Mobile results workspace](docs/assets/screenshots/mobile-results-dark.webp) | +## Repository Layout -## Highlights +```text +. +|-- apps/ +| |-- api/ # Express API and media services +| `-- web/ # React browser application +|-- packages/ +| |-- contracts/ # Shared API DTOs and schemas +| `-- video-core/ # Reusable pure media helpers +|-- scripts/ # Development launcher and repository scripts +|-- docs/ # User, operator, and developer documentation +|-- e2e/ # Playwright browser workflows +|-- data/ # Local runtime storage, untracked +`-- .tmp/ # Local test/review scratch space, untracked +``` + +## Development Commands + +| Command | Purpose | +| --------------------------- | ---------------------------------------------------------------------- | +| `npm run dev` | Build shared packages, then run API and web app together. | +| `npm run dev:api` | Build shared packages, then run the API development service. | +| `npm run dev:web` | Build shared packages, then run the browser app. | +| `npm run build` | Build packages, API, and web. | +| `npm run lint` | Run ESLint with zero warnings allowed. | +| `npm run typecheck` | Build shared packages and run TypeScript checks across workspaces. | +| `npm run test:run` | Build shared packages, run script tests, and run workspace tests once. | +| `npm run test:e2e` | Run Playwright browser workflows through the project E2E runner. | +| `npm run review:ui-screens` | Capture deterministic UI review screenshots into `.tmp/ui-review/`. | +| `npm run check` | Run format check, lint, typecheck, tests, and build. | -- Local FFmpeg execution with bounded job scheduling and cancelation. -- Browser comparison theatre with side-by-side, stacked, overlay, and wipe modes. -- Progressive Prepare/Results source workspace with URL restoration. -- History and storage cleanup for sources, outputs, packages, and temporary files. -- Caption generation through optional local whisper.cpp. -- YouTube import through optional local yt-dlp. -- Shared API contracts and video-core helpers with unit, browser, and real-media integration tests. +See [Testing](docs/testing.md) for coverage, audit, browser, and real-media integration commands. + +## Gallery -## Documentation +| Prepare | Results | Compare | +| ------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | +| ![Prepare workspace with upload, source metadata, and website optimization controls](docs/assets/screenshots/prepare-dark.webp) | ![Results workspace with completed outputs and package controls](docs/assets/screenshots/results-dark.webp) | ![Compare theatre using the wipe divider between original and optimized output](docs/assets/screenshots/compare-wipe-dark.webp) | -- [Documentation index](docs/README.md) -- [Getting started](docs/getting-started.md) -- [User guide](docs/user-guide.md) -- [Configuration](docs/configuration.md) -- [API reference](docs/api.md) -- [Architecture](docs/architecture.md) -- [Testing](docs/testing.md) -- [Brand system](docs/brand-system.md) -- [Troubleshooting](docs/troubleshooting.md) +Prepare demonstrates source admission, local metadata, and the main website workflow. Results demonstrates completed artifacts, selected output details, and package readiness. Compare demonstrates quality review with synchronized media controls. + +| Custom Export | Mobile | +| ---------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | +| ![Custom export controls for codec, container, dimensions, quality, and audio settings](docs/assets/screenshots/custom-export-dark.webp) | ![Mobile results workspace with bottom navigation and package action area](docs/assets/screenshots/mobile-results-dark.webp) | + +Custom Export demonstrates advanced settings for manual exports. Mobile demonstrates the same information architecture adapted to compact navigation. ## Privacy And Security -Media processing is local by default. The app stores sources, outputs, temporary files, and the manifest under the configured storage root or Docker volume. Optional yt-dlp imports contact YouTube because they download from the URL you provide; optional whisper.cpp transcription runs locally. +WVO is local-first, not browser-only. The browser communicates with the local WVO API. The API invokes FFmpeg/FFprobe, writes sources and outputs to managed local storage, and serves previews and downloads back to the browser. -The API has no authentication and is intended for trusted local use. Binding to a LAN address requires `ALLOW_LAN_ACCESS=true`; only do that on a trusted network. See [Privacy](PRIVACY.md) and [Security](SECURITY.md). +By default, source and output media remain within managed local storage on the user's machine. Optional yt-dlp import contacts the provided service because it downloads from the URL you provide. Optional whisper.cpp caption generation runs locally with the configured executable and model. -## Contributing +The API has no authentication because public hosting is not the supported mode. LAN binding must be explicitly enabled with `ALLOW_LAN_ACCESS=true` and matching `CORS_ORIGIN` values, and should only be used on trusted networks. -Contributions are welcome while the app is in developer beta. Please read [Contributing](CONTRIBUTING.md) before opening a pull request, especially the notes about not committing local media, generated output, coverage, screenshots under `.tmp/`, or environment files. +See [Privacy](PRIVACY.md) and [Security](SECURITY.md). + +## Current Limitations -## License +WVO is still a developer beta for trusted local or trusted LAN use. It has no accounts or cloud sync. FFmpeg and FFprobe are required for core media work; caption generation requires optional whisper.cpp and a local model; URL import requires optional yt-dlp and contacts the source service. Processing speed depends on source media, codec, settings, and hardware. Browser playback support may differ from encoding support. Docker Compose startup is validated in GitHub Actions on Ubuntu, but local platform behavior can still vary. + +## Documentation Map + +**Users:** [Getting Started](docs/getting-started.md), [User Guide](docs/user-guide.md), and [Troubleshooting](docs/troubleshooting.md). + +**Operators:** [Configuration](docs/configuration.md), [Privacy](PRIVACY.md), and [Security](SECURITY.md). + +**Developers:** [Architecture](docs/architecture.md), [API Reference](docs/api.md), and [Testing](docs/testing.md). + +**Project governance:** [Contributing](CONTRIBUTING.md), [Code of Conduct](CODE_OF_CONDUCT.md), [Changelog](CHANGELOG.md), and [Support](SUPPORT.md). + +WVO's current visual and interaction system is documented in [Brand System](docs/brand-system.md). The checked-in slate/iris/ember system and fused WVO monogram are the canonical product identity. + +## Contributing And License + +Contributions are welcome while the app is in developer beta. Please read [Contributing](CONTRIBUTING.md) before opening a pull request, especially the notes about not committing local media, generated output, coverage, screenshots under `.tmp/`, or environment files. MIT. See [LICENSE](LICENSE). diff --git a/docs/brand-system.md b/docs/brand-system.md index 379965c..bd82558 100644 --- a/docs/brand-system.md +++ b/docs/brand-system.md @@ -1,37 +1,149 @@ # Brand System -Web Video Optimizer uses a "precision slate with a controlled spectral transformation" direction: calm local tooling, clear media operations, and restrained moments of color where work is selected, processing, or complete. +This document defines the canonical visual, interaction, and product-language system for the current Web Video Optimizer application. Older logo explorations, green-primary palettes, clapperboard marks, mockups, or brand documents should be treated as historical unless explicitly incorporated here. -## Principles +Web Video Optimizer uses a "precision slate with a controlled spectral transformation" direction: calm local tooling, clear media operations, and restrained moments of color where work is selected, processing, or complete. -- Slate neutrals carry most of the interface. -- Iris marks primary interaction, selection, and focus. -- Ember appears sparingly as the transformation accent. -- Green is reserved for genuine success. -- Blue, amber, and red stay semantic for information, caution, and failure. -- Dense workspaces stay operational and quiet; empty states may express the brand more strongly. +## Purpose And Scope + +This is a product-interface system, not only a logo guide. It governs: + +- Product identity. +- Application chrome. +- Logo usage. +- UI color. +- Typography. +- Layout. +- Components. +- Interaction states. +- Motion. +- Accessibility. +- Writing style. +- Documentation imagery. +- Relationship to future sibling tools. + +Checked-in implementation remains the source of truth for runtime behavior. This document names the intended design language so future changes can stay coherent. + +## Brand Idea + +Precision slate with a controlled spectral transformation. + +- **Precision:** exact media operations, trustworthy measurements, clear statuses, and visible consequences. +- **Slate:** quiet neutral surfaces that let the user's media stay visually dominant. +- **Spectral transformation:** restrained iris-to-ember moments that communicate conversion, movement, and source-to-result comparison. +- **Local:** privacy, ownership, reliability, and visibility into what is happening on this computer. + +WVO should feel: + +- Calm +- Technical +- Precise +- Capable +- Honest +- Local-first +- Non-theatrical +- Outcome-focused + +WVO should not feel: + +- Flashy +- Cyberpunk +- Neon-heavy +- Overly playful +- Enterprise-bureaucratic +- AI-generated marketing language +- Vague or overpromising +- Colorful merely for decoration The intended balance is roughly 80% slate structure, 15% tonal elevation and borders, 4% iris interaction, and 1% ember accent. -## Logo +## Brand Hierarchy And Future Tool Family + +WVO retains its own product name and fused WVO monogram. Future sibling tools should have their own names and marks. + +Shared family resemblance should come from tokens, typography, shape, interaction patterns, application shell behavior, status semantics, and writing voice. Other tools should not reuse the WVO monogram as a suite logo. The WVO spectral logo treatment is product identity, not a generic decoration applied throughout every tool. + +The slate/iris/ember interface system can serve as the starting point for a future shared local-tool design system. Domain content may introduce richer color where appropriate, but application chrome should remain restrained. + +This is a conceptual direction, not an implemented repository architecture: + +```mermaid +flowchart TD + Suite[Local Utility Family] + Shared[Shared product system
tokens, typography, shell, states, voice] + WVO[Web Video Optimizer
media-specific identity] + CC[ColorCraft
color-specific identity] + Hub[Future Tool Dashboard
launcher and registry] + + Suite --> Shared + Shared --> WVO + Shared --> CC + Shared --> Hub +``` + +## Visual System Hierarchy + +```mermaid +flowchart TD + Identity[Product identity] + Foundations[Tokens, typography, spacing, shape] + Components[Controls, panels, states, navigation] + Patterns[Prepare, results, compare, package workflows] + Review[Accessibility, screenshots, automated review] + + Identity --> Foundations + Foundations --> Components + Components --> Patterns + Patterns --> Review +``` + +## Logo Rules The approved mark is a fused WVO monogram. The W and V share overlapping geometry, while the O acts as the terminal output form. The chromatic cyan and ember edge separation is part of the artwork and should remain intact. Canonical app and documentation assets live in `apps/web/public/brand/` so the Vite app, favicon, README, and packaged static paths use the same source files. -Logo variants: +| Asset | Use | +| --------------------------------- | ---------------------------------------------------------------- | +| `WVO-logo-transparent.webp` | Dark letterform variant for light surfaces. | +| `WVO-logo-white-transparent.webp` | White letterform variant for dark surfaces. | +| `WVO-favicon.png` | Small browser chrome favicon derived from the approved monogram. | + +Primary lockup: the monogram paired with visible `Web Video Optimizer` text. This is used in the sidebar, mobile top bar, workspace header, README hero, and documentation. -- `WVO-logo-transparent.webp`: dark letterform variant for light surfaces. -- `WVO-logo-white-transparent.webp`: white letterform variant for dark surfaces. -- `WVO-favicon.png`: favicon derived from the approved monogram for small browser chrome. +Secondary lockup: the monogram by itself. This is acceptable for favicon use, compact chrome where the product name is already visible nearby, or small app marks with an accessible text label elsewhere in the same control. -When the mark sits next to visible "Web Video Optimizer" text, it should be `aria-hidden` to avoid duplicate announcements. Use text alternatives for standalone documentation imagery. +When the mark sits next to visible `Web Video Optimizer` text, it should be `aria-hidden` to avoid duplicate announcements. Use a useful text alternative for standalone documentation imagery. Do not rely on the image alone to name the product in navigational controls. -Clear space should be at least one quarter of the visible monogram width on all sides. Minimum practical rendered widths are about 48px for mobile chrome, 54px for sidebar chrome, 72px for workspace headers, and 180px for documentation or marketing placement. +Sizing guidance: -Do not rotate, stretch, recolor, recreate with text, add containers by default, remove or exaggerate the cyan/ember edges, place on busy media, or use the logo's chromatic treatment as ordinary interface decoration. The logo's cyan and ember edges do not redefine the product palette; the interface remains slate, iris, and ember. +| Placement | Practical rendered width | +| ------------------ | ------------------------------------------------------ | +| Favicon | Browser-controlled favicon dimensions. | +| Mobile header | About 48px. | +| Sidebar chrome | About 54px to 58px. | +| Workspace header | About 72px to 86px. | +| Documentation hero | About 180px to 360px. | +| Empty state | Large enough to be recognizable, but paired with text. | -## Palette +Clear space should be at least one quarter of the visible monogram width on all sides. Use the dark asset on light surfaces and the white asset on dark surfaces. Backgrounds should be quiet slate, white, or transparent. Do not place the logo over busy media or high-contrast patterns. + +Do not: + +- Recreate the logo using text. +- Rotate, stretch, crop, or distort the mark. +- Recolor the cyan and ember edge treatment. +- Separate the cyan and ember edges from the letterform. +- Use the logo gradient as an ordinary button background. +- Put the logo inside a colored tile by default. +- Animate the logo continuously. +- Use the mark as a loading spinner. +- Place the mark on busy media without a quiet background. +- Let sibling applications use the WVO mark. + +The logo's cyan and ember edges do not redefine the product palette. The interface remains slate, iris, and ember. + +## Color And Token Architecture Dark theme: @@ -71,36 +183,226 @@ Light theme: | `--color-warning` | `#8b5c00` | | `--color-danger` | `#b72c3b` | -## Gradients - The canonical spectral gradient is: ```css linear-gradient(120deg, #5f6fe5 0%, #765bc8 54%, #e66a3a 100%) ``` -Use it for the logo, thin brand accents, active processing progress, empty-state atmosphere, and selected transformation indicators. Do not use it as every button fill, panel border, page background, ordinary label treatment, or semantic status substitute. - -Ambient fields may appear behind empty or startup states only. They must stay subtle, static, behind content, and disabled under forced-colors. - -## Typography And Shape - -The app uses a system stack centered on Segoe UI Variable, Segoe UI, Inter when locally available, system-ui, and sans-serif. Use weight and spacing before adding extra color. +Token groups: + +- **Application structure:** app, sidebar, workspace, surface, recessed, elevated, hover, selected. +- **Text hierarchy:** primary, secondary, subtle, disabled. +- **Interaction:** primary, primary hover, primary pressed, focus ring. +- **Transformation:** ember, ember bright, spectral gradients. +- **Status:** success, info, warning, danger. +- **Media:** media background, overlays, scrims. +- **Borders and overlays:** subtle, strong, emphasis, overlay, scrim. +- **Gradients:** brand spectral, processing, ambient field. + +| Purpose | Token | Appropriate use | +| ------------------- | --------------------------- | ----------------------------------------------------------- | +| Primary interaction | `--color-primary` | Main actions, focus, selected states. | +| Transformation | `--color-ember` | Active processing or source-to-output emphasis. | +| Success | `--color-success` | Completed output or valid result. | +| Information | `--color-info` | Neutral capability or help status. | +| Warning | `--color-warning` | Degraded capability or caution. | +| Danger | `--color-danger` | Failure and destructive action. | +| Brand accent | `--gradient-brand-spectral` | Logo-adjacent accents and selected transformation emphasis. | +| Processing | `--gradient-processing` | Progress where conversion is actively happening. | + +`--color-primary` is iris. It is for interaction and selection. `--color-ember` is transformation. It should not replace warning or destructive color. `--color-success` is green and only means genuine completion, validity, or healthy state. `--gradient-brand-spectral` is a brand accent; `--gradient-processing` is currently the same gradient used for progress. + +Appropriate examples: + +- Use iris for the primary `Optimize for website` action. +- Use the processing gradient in a progress bar. +- Use success for completed output and storage health. +- Use warning when FFmpeg is missing, storage is low, or compatibility needs review. +- Use danger for failed jobs and deletion. + +Inappropriate examples: + +- Do not use ember for destructive delete controls. +- Do not use success green as the primary brand color. +- Do not fill every button with the spectral gradient. +- Do not use color alone to communicate status. +- Do not add extra decorative colors to application chrome. + +## Typography + +The app uses a system stack centered on Segoe UI Variable, Segoe UI Variable Text, Segoe UI, Inter when locally available, system-ui, and sans-serif. Monospace text uses ui-monospace, SFMono-Regular, Consolas, Liberation Mono, and monospace. + +Hierarchy should be created primarily through size, weight, spacing, and grouping. Avoid excessive color, uppercase text, and badges. + +| Role | Token | Use | +| ------------- | ---------------------- | ---------------------------------------------- | +| Product title | `--font-product-title` | Sidebar and compact product naming. | +| Page title | `--font-page-title` | Workspace header title. | +| Section title | `--font-section-title` | Major panels and feature sections. | +| Card title | `--font-card-title` | Output rows, compact headings, cards. | +| Body | `--font-body` | Main explanatory copy. | +| Compact body | `--font-body-compact` | Dense panels, help copy, descriptions. | +| Metadata | `--font-metadata` | File details, small status labels, timestamps. | +| Metrics | `--font-metric` | Sizes, savings, headline measurements. | +| Code | `--font-code` | Commands, filenames, paths, snippets. | + +Writing rules: + +- Filenames should remain sentence-case as entered and wrap or truncate safely. +- Codec names should use their real labels: `H.264`, `AV1`, `VP9`, `AAC`, `Opus`, `libx264`, `libaom-av1`, `libopus`. +- Dimensions should use `1280 x 720` in prose and UI text when possible. +- Durations should use compact readable labels such as `0:41` or `1m 05s` depending on context. +- File sizes should be human-readable and include units. +- Button labels should describe the action: `Optimize for website`, `Create package`, `Download original`. +- Technical metadata can be dense, but it should stay scannable and should not become promotional copy. + +## Shape, Spacing, And Elevation + +The spacing system is derived from 4px increments: + +- `--space-1`: 4px +- `--space-2`: 8px +- `--space-3`: 12px +- `--space-4`: 16px +- `--space-5`: 20px +- `--space-6`: 24px +- `--space-7`: 32px +- `--space-8`: 40px +- `--space-9`: 48px + +Radii: + +- Controls use `--radius-control` at 8px. +- Cards use `--radius-card` at 10px. +- Media uses `--radius-media` at 8px. +- Dialogs use `--radius-dialog` at 12px. +- Major empty states and theater surfaces use `--radius-hero` at 14px. +- Pills use `--radius-pill`. + +Dark mode relies on tonal elevation and borders more than shadows. Shadows are restrained and reserved for dialogs, floating mobile navigation, and true overlays. Nested cards should be limited. Prefer one parent panel with recessed fields or rows over multiple card-within-card layers. + +## Application Shell + +The WVO shell is made of: + +- Desktop sidebar. +- Workspace. +- Workspace header. +- Current-source context. +- Recent-source area. +- Theme control. +- Mobile top bar. +- Mobile bottom navigation. +- Contextual bottom action area. + +Sidebar navigation communicates place. Workflow pills communicate progress or mode. The topbar communicates current context. Content panels communicate tasks. Mobile navigation must preserve the same information architecture rather than merely collapse desktop controls. + +Verified responsive breakpoints: + +- At `1280px` and below, the sidebar narrows and multi-column work areas collapse. +- At `1024px` and below, the desktop sidebar is replaced by a mobile top bar and bottom navigation. +- At `768px` and below, media controls, comparison, results, settings, package, and history layouts become single-column or mobile-focused. +- At `430px` and below, compact header and lightbox controls tighten further. + +## Components And Interaction Grammar + +| Pattern | Use | Avoid | +| ------------------ | --------------------------------------------------------- | ----------------------------------------------------- | +| Primary button | One dominant action in a task area. | Multiple competing primary actions in the same panel. | +| Secondary button | Normal actions that are not the main next step. | Styling destructive work as neutral. | +| Quiet button | Low-emphasis utility and reset actions. | Hiding important workflow actions. | +| Icon button | Compact known actions with accessible names or titles. | Unlabeled unfamiliar actions. | +| Destructive action | Delete, remove, cancel where data or work may be lost. | Ember or success styling. | +| Status badge | Short state with text and icon support. | Color-only state. | +| Notice | Errors, warnings, degraded startup, recoverable problems. | Browser alerts as primary app messaging. | +| Panel | A bounded task or information area. | Deeply nested cards. | +| Drop zone | File upload and source preview. | General empty-state decoration. | +| Field | Metadata, settings, and compact source details. | Long prose blocks. | +| Metric | Sizes, savings, counts, durations. | Decorative numbers without context. | +| Progress | Queued and running work. | Fake activity for idle states. | +| Context menu | Secondary row actions. | Primary workflow commands. | +| Dialog | Focused overlays such as poster preview. | Replacing ordinary page content. | +| Selected row | Current source or output selection. | Selection that relies only on background color. | +| Empty state | No source, no history, unavailable route. | Marketing hero copy. | + +Only one dominant primary action should appear per task area. Destructive actions remain visually and semantically distinct. Selected state must not rely only on background color. Status must include text or icon support. Hover should not cause distracting movement. Disabled controls should remain readable. Browser alerts should not replace application notices. + +## Motion + +Motion communicates state, not personality by itself. + +- Use existing motion tokens: `--motion-fast`, `--motion-base`, and `--motion-slow`. +- Processing animation may use the spectral direction. +- No decorative continuous animation in operational workspaces. +- Honor `prefers-reduced-motion`. +- Avoid hover scaling for ordinary controls. +- Progress and state changes should not shift surrounding layout unexpectedly. +- Dialog and overlay motion should be brief and should preserve focus behavior. + +## Writing Voice + +WVO copy should: + +- Lead with the task or outcome. +- Use plain technical language. +- State what happens locally. +- Explain consequences before destructive actions. +- Describe errors with a recovery action. +- Avoid inflated claims such as "revolutionary", "perfect", "magic", or "intelligent". +- Avoid unexplained jargon. +- Avoid vague AI-style headings such as "Unlock the power of". + +Approved examples: + +- `Optimize for website` +- `Create package` +- `Download original` +- `FFmpeg was not found. Install it or configure its path.` +- `This URL points to a source ID that is not in the local library on this computer.` +- `Caption generation needs whisper.cpp and a model.` + +Disallowed examples: + +- `Begin advanced transformation` +- `Unleash perfect video magic` +- `Something went wrong` +- `AI-powered optimization engine` +- `Revolutionary media workflow` + +## Accessibility And Review + +Normal text should meet at least 4.5:1 contrast and large text at least 3:1. Status must not rely on color alone. + +Accessibility requirements: + +- Keyboard navigation reaches every interactive control. +- Focus visibility remains clear in dark, light, and forced-colors modes. +- Forced colors receive readable simplified treatments. +- Reduced motion receives static or simplified treatments. +- Status includes text or icon support. +- Dialogs manage focus and restore focus when closed. +- Icon-only controls have accessible names. +- Media controls expose play, pause, seek, speed, mute, and captions where applicable. +- Responsive controls remain large enough to operate and text remains readable. +- Screenshot review should check both structure and readability. +- Playwright and axe checks remain part of release review. + +Do not remove focus outlines. Do not communicate completion, warning, or failure with color alone. + +## Documentation And Screenshot Rules -Controls use approximately 8px radius, cards 10px, and dialogs or major empty states 14px. Dark mode relies on tonal elevation and borders more than shadows. - -## Interaction And Status - -Primary actions are solid iris with white text. Secondary actions use quiet slate surfaces. Selected states use an iris rail or border plus a tonal shift. Processing may use iris-to-ember progress. Completed states use green with text or icon support. Warning, danger, and destructive states stay amber or red and must not be replaced with ember. - -Focus uses the iris focus ring and remains visible in dark, light, and forced-colors modes. Do not remove focus outlines. - -## Accessibility - -Normal text should meet at least 4.5:1 contrast and large text at least 3:1. Status must not rely on color alone. Reduced-motion and forced-colors users should receive simplified, readable treatments. Screenshot review and Playwright accessibility checks are part of the release process. +Curated README screenshots are stored in `docs/assets/screenshots/`. Full deterministic review captures are generated into `.tmp/ui-review/` by `npm run review:ui-screens` and must not be committed. -## Screenshot Examples +Screenshot rules: -Curated README screenshots are stored in `docs/assets/screenshots/`. Full deterministic review captures are generated into `.tmp/ui-review/` by `npm run review:ui-screens` and must not be committed. +- Screenshots must represent the current UI. +- Screenshots must use mocked review fixtures. +- Dark and light captures should demonstrate equivalent information architecture. +- Avoid screenshots that merely repeat the same page state. +- Use descriptive alt text focused on what the interface demonstrates. +- Do not decorate screenshots with arbitrary external frames unless needed for explanatory documentation. +- README diagrams should use the same restrained terminology as the app. +- The screenshot set should cover dark and light themes, Prepare, Results, Compare, Custom Export, mobile, startup failure, degraded startup, processing, completed, warning, and selected-output states when those states are relevant to the documentation task. -The screenshot set should cover dark and light themes, Prepare, Results, Compare, Custom Export, mobile, startup failure, degraded startup, processing, completed, warning, and selected-output states. +WVO's current direction remains precision slate, controlled spectral transformation, slate-dominant chrome, iris for primary interaction, ember used sparingly for transformation, green only for genuine success, and blue, amber, and red reserved for semantic information, warning, and failure. diff --git a/docs/user-guide.md b/docs/user-guide.md index 37d08c6..50545d2 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -40,7 +40,7 @@ Processed historical sources open directly to Results. New or unprocessed source ![Compare theatre](assets/screenshots/compare-wipe-dark.webp) -Compare is a theatre-style view for checking visual quality. It supports multiple layouts and modes, including side-by-side, stacked, overlay, and wipe comparison. Playback can be synchronized across videos. +Compare is a theatre-style view for checking visual quality. It supports grid layouts, wipe comparison, and A/B comparison. Playback can be synchronized across videos. The URL restores selected output, mode, layout, and visible versions. Playback time, volume, zoom, pan, wipe position, and fullscreen are intentionally treated as temporary review state.