- Fix processor-counts API to correctly read JSON counts: - YOLO: use frames.length (was returning null) - CUT: prioritize scenes.length over frame_count - Result: YOLO 1963 frames, CUT 25 scenes (correct) - Fix ASRX field name conversion: - Convert start_time/end_time → start/end for ASRX compatibility - Prefer frame-based positioning over time-based - Document issues in issues_2026-06-21.md: - Issue 6: ASRX field name mismatch - Issue 7: processor-counts API null values
8.9 KiB
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 <module>
import cv2
ModuleNotFoundError: No module named 'cv2'
Resolution
pip3 install opencv-python
Recommendation
- Add Python dependency check in worker startup
- Document required Python packages in README
- Add
requirements.txtwith 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:
- No job exists for the file
- Job is complete (all processors finished)
- Worker is stuck/not processing
Expected Behavior (from docs)
{
"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
statusfield 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:
// 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
- Install OpenCV:
pip3 install opencv-python - Add worker health monitoring
- Fix progress API to return status for completed jobs
Short-term
- Add Python dependency validation in worker
- Document Redis prefix configuration
- Improve frontend status verification
Long-term
- Add
requirements.txtfor processor scripts - Implement worker auto-restart mechanism
- Add comprehensive logging for job lifecycle
- 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:
# Line 137-138
start_sec = seg["start"] # KeyError: 'start'
end_sec = seg["end"] # KeyError: 'end'
ASR Output Structure (Current)
{
"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:
# 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
- Frame-based is precise - use
start_frame/end_framedirectly when available - Time is auxiliary - derive from frames:
start_time = start_frame / fps - Backward compatible - fallback to
start/endorstart_time/end_timefor older ASR output
Recommendation
- Make asrx_processor.py backward compatible with both formats
- Add validation: check if asrx segments > 0 before marking complete
- Log error when ASRX returns 0 segments from non-empty ASR input
- Add unit test for ASR/ASRX format compatibility