# MoMentry Playground - AGENTS.md ## 概述 MoMentry Playground 是一個整合式桌面應用程式,提供: - 多格式媒體播放(視頻、音頻、圖片) - Frame-精確的視頻控制 - ASR 字幕顯示(可開關) - YOLO 檢測框疊加(可開關) - Chunk 導航標記(可開關) - 與 momentry_core 處理模組的進度監控 - 自然語言搜尋 ## 技術棧 | 元件 | 技術 | |------|------| | 語言 | Rust 2021 | | 桌面框架 | tao + wry | | 視頻播放 | SDL2 + FFmpeg | | 前端 | HTML/CSS/JS (WebView) | | 後端接口 | HTTP API (momentry_core port 3002) | | 數據庫 | PostgreSQL, MongoDB, Qdrant (via API) | | 緩存 | LRU (YOLO frame cache) | --- ## 構建/測試/代碼質量命令 ### 構建 ```bash # Debug 構建 cargo build # Release 構建 cargo build --release # 運行 cargo run -- --video "/path/to/video.mov" # 指定參數 cargo run --release -- \ --video "/Users/accusys/test_video/Old_Time_Movie_Show_-_Charade_1963.HD.mov" \ --asr "/Users/accusys/momentry_core_0.1/output/39567a0eb16f39fd.asr.json" \ --yolo "/Users/accusys/test_video/Old_Time_Movie_Show_-_Charade_1963.HD.yolo.json" ``` ### 測試 ```bash # 運行所有測試 cargo test # 運行單個測試 cargo test test_name # 運行並顯示輸出 cargo test -- --nocapture # 運行 doc tests cargo test --doc ``` ### 代碼質量 ```bash # 格式化代碼 cargo fmt # 檢查格式化 cargo fmt -- --check # Lint + 自動修復 cargo clippy --fix --allow-dirty --allow-staged # Lint 檢查 cargo clippy # 類型檢查 cargo check # 完整檢查 cargo build --all-targets ``` --- ## 代碼風格指南 ### 格式規範 - **最大行長**: 100 字符 - **縮進**: 4 空格(使用 `rustfmt` 自動處理) ### 命名慣例 ```rust // 類型/結構體/枚舉: PascalCase struct VideoPlayer; enum PlaybackState; trait MediaViewer; // 函數/方法/變量: snake_case fn play_video(); let current_frame = 0; // 常量: SCREAMING_SNAKE_CASE const MAX_FRAME_BUFFER: usize = 10; ``` ### 錯誤處理 ```rust use anyhow::{Context, Result, anyhow}; fn load_video(path: &str) -> Result { let file = File::open(path) .with_context(|| format!("Failed to open video: {}", path))?; Ok(file) } #[derive(Debug, thiserror::Error)] pub enum PlayerError { #[error("Codec not supported: {0}")] UnsupportedCodec(String), #[error("Seek failed: {0}")] SeekFailed(String), } ``` ### 模塊結構 ```rust // src/lib.rs pub mod player; pub mod overlay; pub mod web; pub mod config; // src/player/mod.rs pub mod video; pub mod ffmpeg; pub mod renderer; pub mod state; pub use video::Video; pub use state::{PlayerState, PlaybackState}; ``` --- ## 快捷鍵定義 | 快捷鍵 | 功能 | Toggle | |--------|------|--------| | `Space` | 播放/暫停 | - | | `←` | 上一幀 | - | | `→` | 下一幀 | - | | `Shift+←` | 後退 1 秒 | - | | `Shift+→` | 前進 1 秒 | - | | `S` | 字幕顯示 | ✅ | | `Y` | YOLO 疊加 | ✅ | | `C` | Chunk 標記 | ✅ | | `M` | 靜音 | ✅ | | `+` / `=` | 放大 | - | | `-` | 縮小 | - | | `0` | 重置縮放 | - | | `R` | 重置視圖 | - | | `F` | 全屏 | - | | `[` | 上一 Chunk | - | | `]` | 下一 Chunk | - | | `/` | 開啟搜尋 | - | | `Esc` | 關閉面板 | - | --- ## 命令列參數 ```bash momentry [OPTIONS] Options: -v, --video Video file path -a, --asr ASR JSON file path -y, --yolo YOLO JSON file path -w, --width Window width (default: 1280) -h, --height Window height (default: 720) --fullscreen Start in fullscreen mode --locale UI language (en, zh-TW) --help Show help ``` --- ## 數據格式規範 ### ASR JSON ```json { "language": "en", "language_probability": 0.99, "segments": [ { "start": 0.0, "end": 19.04, "text": "Hello and welcome..." } ] } ``` ### YOLO JSON ```json { "metadata": { "fps": 59.94, "total_frames": 412343, "width": 1920, "height": 1080 }, "frames": { "100": { "frame_number": 100, "time_seconds": 1.668, "detections": [ { "class_name": "person", "confidence": 0.85, "x1": 150, "y1": 200, "x2": 400, "y2": 800 } ] } } } ``` **座標系**: 絕對像素座標 (0 ~ width/height) --- ## 服務連接配置 ```yaml PostgreSQL: host: localhost port: 5432 database: momentry user: accusys password: Test3200 Redis: host: localhost port: 6379 password: accusys Qdrant: host: localhost port: 6333 collection: AccusysDB api_key: Test3200Test3200Test3200 API Server: host: 127.0.0.1 port: 3002 Ollama: host: localhost port: 11434 ``` --- ## 測試數據 ```bash VIDEO="/Users/accusys/test_video/Old_Time_Movie_Show_-_Charade_1963.HD.mov" ASR="/Users/accusys/momentry_core_0.1/output/39567a0eb16f39fd.asr.json" YOLO="/Users/accusys/test_video/Old_Time_Movie_Show_-_Charade_1963.HD.yolo.json" ``` --- ## 項目結構 ``` momentry_playground/ ├── Cargo.toml ├── src/ │ ├── main.rs # 入口 │ ├── lib.rs # 模組導出 │ ├── config.rs # 命令列解析 │ ├── player/ # 視頻播放 │ │ ├── mod.rs │ │ ├── video.rs # 播放控制 │ │ ├── ffmpeg.rs # FFmpeg 解碼 │ │ ├── renderer.rs # SDL2 渲染 │ │ └── state.rs # 播放狀態 │ ├── overlay/ # 疊加層 │ │ ├── mod.rs │ │ ├── asr.rs # ASR 載入 │ │ └── yolo.rs # YOLO 載入 (LRU cache) │ └── web/ # WebView │ ├── mod.rs │ └── bridge.rs # JS <-> Rust IPC ├── web/ │ ├── index.html # 主 UI │ ├── styles.css # 樣式 │ └── app.js # 前端邏輯 ├── AGENTS.md └── README.md ``` --- ## 外部依賴 ### FFmpeg (必需) ```bash # macOS brew install ffmpeg # Linux sudo apt install ffmpeg # 驗證 ffmpeg -version ffprobe -version ``` ### yt-dlp (YouTube 支援) ```bash brew install yt-dlp pip install yt-dlp ``` --- ## 開發工作流 ### 1. 創建功能分支 ```bash git checkout -b feature/video-controls ``` ### 2. 開發與測試 ```bash cargo test feature_name cargo clippy --fix cargo fmt cargo build --release ``` ### 3. 提交 ```bash git commit -m "feat(player): add frame-precise seeking" git commit -m "fix(controls): correct volume sync" ``` ### 4. 推送與 PR ```bash git push -u origin feature/video-controls # 在 Gitea 創建 PR → main ``` --- ## 常見問題 ### Q: FFmpeg 路徑找不到 在 `src/player/ffmpeg.rs` 中指定路徑: ```rust Command::new("/opt/homebrew/bin/ffmpeg") ``` ### Q: YOLO 檔案太大 (483MB) 使用 LRU cache 緩存幀: ```rust const CACHE_SIZE: usize = 60; // 只緩存前後 30 幀 cache: LruCache> ``` ### Q: 編譯緩慢 ```bash cargo install sccache export RUSTC_WRAPPER=sccache ``` --- ## 多語言支援 (i18n) 目前界面語言為 English。擴展時: 1. 在 `web/` 添加 `locales/` 目錄 2. 建立 `en.json`, `zh-TW.json` 等檔案 3. 在 `app.js` 載入對應語言檔案 4. 使用 `data-i18n` 屬性標記翻譯元素 --- ## 實施優先順序 | Phase | 功能 | 優先級 | |-------|------|--------| | 1 | 基礎播放器 | P0 | | 2 | ASR 字幕 | P1 | | 3 | YOLO 疊加 | P1 | | 4 | Chunk 標記 | P2 | | 5 | Zoom/Pan | P1 | | 6 | Vector 搜尋 | P2 | | 7 | 進度監控 | P3 | | 8 | 雲端/YouTube | P3 |