2025/09/20

Desktop Media Cleanup App — Requirements v1.0

Desktop Media Cleanup App — Requirements v1.0

1) Overview & Goals

A desktop utility that helps users quickly triage photos and videos by assigning scores and bulk‑deleting low‑scored media. The app indexes media in a chosen root folder, previews items one‑by‑one, lets users adjust a per‑file score via mouse clicks, and automates deletion of files that were marked for removal.

Primary goals

  • Fast, keyboard/mouse‑driven triage of large media libraries.

  • Clear progress feedback and a definitive “clean up completed” state.

  • Safe, reversible (optional) delete flow, per user confirmation.

Out of scope (v1): Cloud sync integrations, facial recognition, deduplication, format conversion, editing.


2) Platforms & Tech Assumptions

  • Target OS: Windows 10+, macOS 12+, (optional) Linux (Ubuntu LTS).

  • Packaging: Native installers (MSIX/EXE, DMG/PKG, AppImage/Snap optional).

  • Media preview: use OS codecs or a cross‑platform library (e.g., ffmpeg/AVFoundation/DirectShow) for thumbnails and playback.

  • Index store: single file per root (SQLite recommended; JSON allowed for MVP).


3) Core Concepts & Definitions

  • Root Folder: The folder the user chooses to clean; includes all subfolders.

  • Index: On‑disk database of discovered media and their scores/metadata.

  • Score: Integer 1..51..5, default 3 for each indexed file.

    • 1 = reject (to delete), 5 = keep (locked), 2/3/4 = undecided.

  • todelete folder: Destination subfolder under each file’s current parent for files scored 1.


4) User Stories

  1. As a user, I can pick a folder and immediately see its subfolders in a tree with file counts.

  2. As a user, I can preview photos/videos in sequence and change their score quickly with the mouse.

  3. As a user, I can skip items already at score 1 or 5 and focus only on undecided ones.

  4. As a user, I can finish triage and bulk‑delete the 1‑scored files after a clear confirmation.

  5. As a user, I see a "clean up completed" message when every file is either 1 or 5.


5) Functional Requirements

FR-1 Folder Navigation & Tree

  • FR-1.1 The app shows a collapsible folder tree rooted at the selected folder.

  • FR-1.2 Users can toggle among folders and subfolders; selecting a node filters the item list/preview scope.

  • FR-1.3 Each node displays the total media file count (photos + videos) within that folder including all nested subfolders.

FR-2 Indexing

  • FR-2.1 On selecting a root, the app creates/updates an index of photos and videos (configurable extensions: jpg/jpeg/png/heic/webp/mp4/mov/avi/mkv, etc.).

  • FR-2.2 Each discovered file is added with initial score = 3.

  • FR-2.3 The index stores: absolute path, file size, modified time, hash (optional), duration (video), orientation + EXIF date (photo), and current score.

  • FR-2.4 Index updates are incremental on subsequent launches (detect adds/removes/moves).

  • FR-2.5 Index file is stored at the root as .media_index.sqlite (or .json for MVP).

FR-3 Preview & Scoring

  • FR-3.1 The app starts previewing media from the current selection/folder.

  • FR-3.2 Right‑click on preview adds +1 to the current file’s score (max 5).

  • FR-3.3 Left‑click on preview deducts −1 from the current file’s score (min 1).

  • FR-3.4 Keyboard shortcuts (optional but recommended): = +1, = −1, Space = next, Backspace = previous.

  • FR-3.5 The preview loop auto‑skips any item with score 1 or 5.

  • FR-3.6 When the current pass ends, the app circles back to files that are still score 2/3/4 until all files are 1 or 5.

  • FR-3.7 Video preview defaults to the first 5 seconds (toggle to full playback); photo preview fits to window with zoom/pan.

FR-4 Move & Delete

  • FR-4.1 Whenever a file’s score becomes 1, the app moves it to a sibling folder named todelete under its original parent (create if missing). Preserve subfolder structure relative to the root.

  • FR-4.2 When all files within the selected scope are either 1 or 5, show “clean up completed”.

  • FR-4.3 Prompt: “Delete all files scored 1?” If the user confirms, permanently delete those files (see Safety below), then delete the index file.

  • FR-4.4 After deletion, recursively remove empty folders (folders with no files in them or any of their subfolders).

FR-5 Progress & Status

  • FR-5.1 Show counts: total, scored 1, scored 5, remaining (2/3/4).

  • FR-5.2 Status bar indicates current folder, preview position (e.g., 120/3,482), and pass number.

FR-6 Settings

  • FR-6.1 Configure included file extensions.

  • FR-6.2 Toggle confirm‑before‑move (default off) and confirm‑before‑delete (default on, cannot be disabled in v1).

  • FR-6.3 Option to send deletes to OS Trash/Recycle Bin instead of hard delete (recommended default).


6) Non‑Functional Requirements

  • Performance: Index 50k files in ≤ 5 minutes on SSD; preview latency ≤ 150 ms for images, ≤ 500 ms to start video.

  • Reliability: Crash‑safe index writes (transactional); resume last session state.

  • Security: No network access by default; operates only on local paths with explicit user selection.

  • Accessibility: All actions available via keyboard; high‑contrast option.


7) UX & Screens

  • Main layout: Left = folder tree with counts; center = preview; right = metadata + score display; bottom = controls & status.

  • Contextual HUD: Big overlay briefly shows new score after click (e.g., “Score: 4”).

  • Completion dialog: Summary of items to be deleted; irreversible‑action warning.


8) Data Model (SQLite Suggestion)

TABLE media (
  id INTEGER PRIMARY KEY,
  path TEXT UNIQUE NOT NULL,
  rel_path TEXT NOT NULL,
  folder_id INTEGER NOT NULL,
  type TEXT CHECK(type IN ('photo','video')),
  score INTEGER NOT NULL DEFAULT 3 CHECK(score BETWEEN 1 AND 5),
  size_bytes INTEGER,
  mtime_utc TEXT,
  duration_ms INTEGER,
  exif_datetime TEXT,
  hash TEXT,
  FOREIGN KEY(folder_id) REFERENCES folders(id)
);

TABLE folders (
  id INTEGER PRIMARY KEY,
  path TEXT UNIQUE NOT NULL,
  rel_path TEXT NOT NULL,
  total_count INTEGER NOT NULL DEFAULT 0
);

INDEX idx_media_folder ON media(folder_id);
INDEX idx_media_score ON media(score);

9) Scoring & Preview Algorithm (Reference)

function triageLoop(scope):
  queue = all media in scope where score IN (2,3,4)
  while queue not empty:
    item = queue.popNext()
    showPreview(item)
    action = waitForUserClick()
    if action == RIGHT_CLICK: item.score = min(5, item.score + 1)
    if action == LEFT_CLICK:  item.score = max(1, item.score - 1)
    persistScore(item)
    if item.score == 1: moveToToDelete(item)
    if item.score in (2,3,4): queue.enqueue(item) // circle back later
  if all items in scope have score in (1,5):
    showCleanupCompleted()
    if confirm("Delete all files scored 1?"):
      deleteAllScoreOne(scope)
      deleteIndex()
      pruneEmptyFolders(scope.root)

10) File Operations & Safety

  • Moves and deletes must be atomic where possible; fall back with clear error messages.

  • During delete: if setting is “send to OS Trash,” use platform APIs; otherwise perform hard delete after confirmation.

  • Skip/record failures (e.g., permission denied, locked file) and continue; show a completion report.


11) Module Breakdown (Modularization)

  • app/

    • main (bootstrap, window, routing)

    • config (settings load/save)

    • i18n (strings)

  • indexer/

    • scanner (walk filesystem)

    • metadata (EXIF/video probes)

    • store (SQLite/JSON abstraction)

  • preview/

    • image_viewer (render, zoom, pan)

    • video_player (playback, scrub)

  • scoring/

    • controller (event handling, queue policy)

    • state (session state, resume)

  • ui/

    • folder_tree (counts, toggles)

    • status_bar, hud, dialogs

  • ops/

    • mover (to todelete)

    • deleter (trash/hard delete, prune empty dirs)

    • reporter (summary & logs)

Each module ships in a separate source file (or cohesive files) with narrow interfaces to ease updates and feature additions.


12) Acceptance Criteria

  • AC‑1: Selecting a root shows a tree with accurate counts (children included).

  • AC‑2: All files are assigned score 3 on first index.

  • AC‑3: Left/Right clicks adjust score exactly by −1/+1; scores clamp to 1..51..5.

  • AC‑4: Preview loop never shows items already at 1 or 5.

  • AC‑5: Files at score 1 are moved to todelete/ under their original parents.

  • AC‑6: When no items remain at 2/3/4, “clean up completed” appears.

  • AC‑7: On confirmation, all score‑1 files are deleted, the index file is removed, and empty folders are pruned.


13) Future Enhancements (Non‑blocking)

  • Duplicate detection (perceptual hash).

  • Sorting heuristics (by similarity, face detection, blurriness).

  • Multi‑root projects; exportable CSV reports.

  • Undo/redo stack and checkpoints.


14) Technology Options for a Windows App — Comparison

The app is Windows‑first with heavy filesystem work and image/video preview. Below is a pragmatic comparison of common stacks.

14.1 Quick Matrix (higher is better)

Tech Perf. Memory Dev Speed Native Win Integration Cross‑Platform Media Preview Maturity Packaging
.NET WPF (.NET 8) 5 4 4 5 2 5 MSIX/WiX/WinGet
.NET WinUI 3 (Windows App SDK) 5 4 3 5 2 5 MSIX/WinGet
.NET MAUI (Windows target) 4 4 3 4 4 3 MSIX
Avalonia UI (.NET) 4 4 4 3 5 3 MSIX/others
Qt (C++/QML) 5 5 3 4 5 5 MSI/WiX
Flutter (Windows) 4 4 3 3 5 3 MSIX
Electron (JS/TS) 3 2 5 3 5 4 Squirrel/MSIX
Tauri (Rust + WebView) 4 5 3 3 5 3 MSI/MSIX
Python (PySide/PyQt/PyInstaller) 3 3 4 3 5 3 EXE/MSI

Legend: 1–5 relative score. Memory = smaller footprint → higher score.

14.2 Notes & Pros/Cons

.NET WPF

  • Pros: Battle‑tested on Windows, excellent filesystem APIs, stable MVVM ecosystem, great tooling (Visual Studio, Rider). Easy thumbnails via WIC; video via Media Foundation or FFmpeg wrappers. Mature SQLite + EXIF libs.

  • Cons: Windows‑only; legacy XAML patterns but still first‑class.

  • Use when: You want the most stable Windows‑native path with top‑tier performance and full access to Windows codecs.

.NET WinUI 3 (Windows App SDK)

  • Pros: Modern WinUI controls, high‑DPI, fluent styling, future‑facing Windows stack. Deep integration with Windows features.

  • Cons: Some APIs/tooling still evolving; smaller community than WPF. Edge cases with third‑party controls vs WPF.

  • Use when: You want modern Windows look/feel and can accept newer‑stack tradeoffs.

.NET MAUI (Windows)

  • Pros: Same codebase can target Mac/iOS/Android; Windows layer sits on WinUI 3. Good for shared business logic.

  • Cons: Desktop maturity below WPF/WinUI; media preview/video plugins less polished for Windows.

  • Use when: Cross‑platform is a real requirement and you’re already in .NET.

Avalonia UI (.NET)

  • Pros: Cross‑platform WPF‑like XAML; good theming; solid desktop focus.

  • Cons: Fewer off‑the‑shelf media components; you’ll likely embed FFmpeg/LibVLC for video.

  • Use when: You want .NET + cross‑platform with a desktop‑first mindset.

Qt (C++/QML/QtQuick)

  • Pros: High performance, native feel, very mature multimedia (Qt Multimedia) and EXIF/DB tooling, excellent for large libraries.

  • Cons: C++ complexity; commercial licensing for some use cases; larger dev ramp.

  • Use when: You need top performance and true cross‑platform with robust media.

Flutter (Windows)

  • Pros: Single codebase; fast UI iteration; strong 2D GPU rendering.

  • Cons: Desktop plugins for advanced media/filesystem are still catching up vs native.

  • Use when: You have Flutter expertise and want cross‑platform UIs.

Electron (JS/TS)

  • Pros: Web skills, rapid UI dev, rich ecosystem. Chromium can preview many image/video formats; Node for filesystem.

  • Cons: Larger memory footprint; packaging/signing friction; native OS feature gaps.

  • Use when: Team is web‑heavy and footprint isn’t critical.

Tauri (Rust + WebView)

  • Pros: Tiny binaries and memory; secure; Rust for native ops; modern WebView front‑end.

  • Cons: Media playback often requires native plugins/FFmpeg; fewer production examples for heavy media.

  • Use when: You want Electron‑style dev with an order‑of‑magnitude smaller footprint and can handle native media plumbing.

Python (PySide/PyQt)

  • Pros: Quick prototyping; rich libraries; Qt underneath.

  • Cons: Packaging size, startup time, and distribution quirks; perf below C#/C++.

  • Use when: You need rapid iteration and internal tooling; less ideal for mass distribution.

14.3 Media‑Specific Considerations for This App

  • Thumbnailing & EXIF: WIC + MetadataExtractor (.NET) or Qt’s QImageReader + Exiv2/QtEXIF are robust.

  • Video preview: Windows Media Foundation (native/.NET wrappers) or FFmpeg/LibVLC for broad codec coverage. Browser engines (Electron/Flutter WebView) support common codecs but may choke on edge formats.

  • Large library indexing: Prefer SQLite (system.data.sqlite/.NET; QtSql/SQLite; rusqlite for Rust). Use incremental scans and file hashing on demand.

14.4 Packaging & Updates

  • Windows‑native: MSIX (WinGet), or MSI/WiX; code‑signing cert required.

  • Web stacks: Electron → Squirrel/MSIX; Tauri → MSI/MSIX. Auto‑update channel recommended but must be code‑signed.

14.5 Recommendation

For Windows‑only and fastest path to a polished tool: .NET (WPF or WinUI 3).

  • Pick WPF if you want maximum stability and ecosystem breadth.

  • Pick WinUI 3 if you want a modern Fluent look and don’t mind a newer stack.

If small footprint and you’re comfortable binding native media: Tauri (Rust backend with FFmpeg/LibVLC + WebView UI).

If cross‑platform with strong media and you’re OK with C++: Qt (C++/QML).

14.6 Suggested Starter Kits

WPF (.NET 8)

  • Imaging: WIC via BitmapImage; EXIF: MetadataExtractor

  • Video: Media Foundation (MediaElement alternatives) or FFmpeg.AutoGen

  • DB: System.Data.SQLite

  • Packaging: MSIX + WinGet

WinUI 3

  • UI: Windows App SDK templates; MediaPlayerElement for video

  • Same EXIF/DB approach as WPF; MSIX packaging

Tauri

  • Backend: Rust (filesystem scan, SQLite, FFmpeg/LibVLC bindings)

  • Frontend: React/Svelte/Vue in WebView; invoke via Tauri commands

  • Installer: Tauri bundler → MSI/MSIX

Qt (C++/QML)

  • Media: QMediaPlayer / QVideoSink, thumbnails with QImageReader

  • EXIF: Exiv2; DB: QtSql + SQLite

  • Installer: WiX/MSI

沒有留言:

張貼留言