# Issue Report: 2026-06-21 ## Issue 1: Worker Process Stuck ### Description Worker process (PID 58279) started on Fri10PM was stuck and not processing new jobs. Last log entry dated 2026-06-20 06:52. ### Symptoms - Jobs triggered via API returned "Processing triggered" but never executed - Redis keys for new jobs were not created - Progress API returned empty response - Worker logs showed old timestamps ### Resolution - Killed stuck worker: `kill 58279` - Restarted worker: `cd /Users/accusys/momentry_core && ./target/release/momentry worker` - New worker PID: 52908 ### Root Cause (Suspected) - Worker process running for extended period without proper cleanup - Possible Redis connection timeout or job queue corruption ### Recommendation - Add worker health check mechanism - Implement automatic worker restart on inactivity timeout - Add logging for job queue polling status --- ## Issue 2: Face/YOLO Processor Failure - Missing OpenCV ### Description Face and YOLO processors failed with `ModuleNotFoundError: No module named 'cv2'` ### Error Log ``` [ERROR] Processor face failed for job d8acb03870f0cc9b14e01f14a7bf24d6: Failed to run "/Users/accusys/momentry_core/scripts/face_processor.py" [ERROR] Processor yolo failed for job d8acb03870f0cc9b14e01f14a7bf24d6: Failed to run "/Users/accusys/momentry_core/scripts/yolo_processor.py" ``` ### Python Test Result ``` python3 /Users/accusys/momentry_core/scripts/face_processor.py --help Traceback (most recent call last): File ".../face_processor.py", line 25, in import cv2 ModuleNotFoundError: No module named 'cv2' ``` ### Resolution ```bash pip3 install opencv-python ``` ### Recommendation - Add Python dependency check in worker startup - Document required Python packages in README - Add `requirements.txt` with all processor dependencies --- ## Issue 3: Redis Prefix Configuration Confusion ### Description Two different Redis namespaces exist: - `momentry:` - Production server (port 3002) - `momentry_dev:` - Playground server (port 3003) ### Impact - Jobs triggered on production server not visible to playground worker - Progress data stored in different namespaces - API proxy needs to match correct prefix ### Current Setup ``` Production Server (port 3002): Redis prefix "momentry:" Playground Server (port 3003): Redis prefix "momentry_dev:" ``` ### Recommendation - Document Redis prefix configuration clearly - Add environment variable for Redis prefix selection - Consider using same prefix for development simplicity --- ## Issue 4: Progress API Behavior ### Description `GET /api/v1/progress/:file_uuid` returns empty response when: 1. No job exists for the file 2. Job is complete (all processors finished) 3. Worker is stuck/not processing ### Expected Behavior (from docs) ```json { "file_uuid": "...", "overall_progress": 71, "processors": [ {"processor_type": "asr", "status": "complete", "progress": 100}, {"processor_type": "yolo", "status": "running", "progress": 65} ] } ``` ### Actual Behavior - Returns empty response (no output) when job complete or missing - Frontend cannot distinguish between "not started" vs "completed" ### Recommendation - Return explicit status for completed jobs (e.g., `{"overall_progress": 100, "status": "completed"}`) - Return 404 when job not found (file never processed) - Add `status` field to response: `pending`, `running`, `completed`, `failed` --- ## Issue 5: Frontend Status Display Bug ### Description Frontend showed "處理中" (processing) status for Gamma Carry file but: - Database status: `registered` (not processed) - No job in Redis - No progress data ### Cause Frontend code sets `f.status = 'processing'` immediately after process trigger, without verifying job creation: ```typescript // LibraryView.vue line 463 if (result.success) { f.status = 'processing' // Sets status prematurely pollProgress(f.file_uuid) } ``` ### Impact - User sees "processing" status but actual processing never started - Misleading UI feedback ### Recommendation - Verify job creation before setting status - Check Redis job key existence - Poll progress API and set status based on actual response - Handle case when progress API returns empty (job not created) --- ## Test Results Summary ### File: Gamma Carry Saves the World..mp4 - UUID: `d8acb03870f0cc9b14e01f14a7bf24d6` - Processing triggered: 2026-06-21 12:13 ### Processor Results | Processor | Status | Output | |-----------|--------|--------| | cut | ✓ Complete | 4825 frames | | asr | ✓ Complete | 0 segments | | face | ✗ Failed | Missing cv2 | | yolo | ✗ Failed | Missing cv2 | | ocr | - Not run | Dependency failed | | pose | - Not run | Dependency failed | ### Redis Keys Created ``` momentry:job:d8acb03870f0cc9b14e01f14a7bf24d6 momentry:progress:d8acb03870f0cc9b14e01f14a7bf24d6 momentry:job:d8acb03870f0cc9b14e01f14a7bf24d6:processor:cut momentry:job:d8acb03870f0cc9b14e01f14a7bf24d6:processor:asr momentry:job:d8acb03870f0cc9b14e01f14a7bf24d6:processor:face momentry:job:d8acb03870f0cc9b14e01f14a7bf24d6:processor:yolo ``` ### API Test Results | API | Status | Note | |-----|--------|------| | `POST /api/v1/file/:uuid/process` | ✓ Works | Job created | | `GET /api/v1/file/:uuid/processor-counts` | ✓ Works | Returns correct counts | | `GET /api/v1/progress/:uuid` | Partial | Empty when complete/missing | | `GET /api/v1/jobs` | - Not tested | No response via proxy | --- ## Recommended Actions ### Immediate 1. Install OpenCV: `pip3 install opencv-python` 2. Add worker health monitoring 3. Fix progress API to return status for completed jobs ### Short-term 1. Add Python dependency validation in worker 2. Document Redis prefix configuration 3. Improve frontend status verification ### Long-term 1. Add `requirements.txt` for processor scripts 2. Implement worker auto-restart mechanism 3. Add comprehensive logging for job lifecycle 4. Create integration tests for processing pipeline --- *Report generated: 2026-06-21 12:15* *Reporter: momentry_studio development session* --- ## Issue 6: ASRX Processor Field Name Mismatch (NEW - 2026-06-22) ### Description ASRX processor fails with `KeyError: 'start'` when processing ASR output. ### Error Log ``` [DEBUG] [ASRX/stderr] KeyError: 'start' [INFO] [ASRX] Result: 0 segments [INFO] Processor asrx completed and verified (0 chunks, 0 frames) ``` ### Root Cause ASR JSON output format changed: - Old format: `{"start": ..., "end": ..., "text": ...}` - Current format: `{"start_time": ..., "end_time": ..., "start_frame": ..., "end_frame": ..., "text": ...}` asrx_processor.py expects old format: ```python # Line 137-138 start_sec = seg["start"] # KeyError: 'start' end_sec = seg["end"] # KeyError: 'end' ``` ### ASR Output Structure (Current) ```json { "start_time": 217.27, "end_time": 224.96, "start_frame": 5209, "end_frame": 5394, "text": "..." } ``` ### File Locations - ASR output: `/Users/accusys/momentry/output/{uuid}.asr.json` - ASRX script: `/Users/accusys/momentry_core/scripts/asrx_processor.py` - Error line: Line 137 ### Impact - ASRX produces 0 segments even when ASR has valid segments - No speaker diarization data generated - File status shows "completed" but asrx output is missing ### Test Case: Charade_YouTube_24fps.mp4 - UUID: `c36f35685177c981aa139b66bbbccc5b` - ASR segments: 1779 (has valid data) - ASRX segments: 0 (failed silently) - Status: `completed` (misleading) ### Fix Required Update asrx_processor.py to prioritize frame-based positioning: ```python # Line 136-149 fix: Use start_frame/end_frame if available for seg in result.get("segments", []): # Prefer frame-based (precise) if "start_frame" in seg and "end_frame" in seg: start_frame = seg["start_frame"] end_frame = seg["end_frame"] start_sec = start_frame / fps end_sec = end_frame / fps else: # Fallback to time-based start_sec = seg.get("start", seg.get("start_time", 0)) end_sec = seg.get("end", seg.get("end_time", 0)) start_frame = int(start_sec * fps) end_frame = int(end_sec * fps) output_result["segments"].append({ "start_time": start_sec, "end_time": end_sec, "start_frame": start_frame, "end_frame": end_frame, "text": seg.get("text", ""), "speaker_id": seg.get("speaker_id", seg.get("speaker", "")), "language": seg.get("language", ""), "lang_prob": seg.get("lang_prob", 0.0), "quality": seg.get("quality", 0.0), }) ``` ### Key Points 1. **Frame-based is precise** - use `start_frame` / `end_frame` directly when available 2. **Time is auxiliary** - derive from frames: `start_time = start_frame / fps` 3. **Backward compatible** - fallback to `start`/`end` or `start_time`/`end_time` for older ASR output ### Recommendation 1. Make asrx_processor.py backward compatible with both formats 2. Add validation: check if asrx segments > 0 before marking complete 3. Log error when ASRX returns 0 segments from non-empty ASR input 4. Add unit test for ASR/ASRX format compatibility