{"record":{"id":"090e64eaebd2b3ba","repo":"harry0703/MoneyPrinterTurbo","slug":"sonilo-video-proxy-generation-timed-out","errorCode":null,"errorMessage":"Sonilo video proxy generation timed out","messagePattern":"Sonilo video proxy generation timed out","errorType":"exception","errorClass":"SoniloError","httpStatus":null,"severity":"error","filePath":"app/services/sonilo.py","lineNumber":185,"sourceCode":"        \"-crf\",\n        \"30\",\n        \"-pix_fmt\",\n        \"yuv420p\",\n        \"-movflags\",\n        \"+faststart\",\n        proxy_path,\n    ]\n    try:\n        result = subprocess.run(\n            command,\n            capture_output=True,\n            text=True,\n            timeout=600,\n            check=False,\n        )\n    except subprocess.TimeoutExpired as exc:\n        _remove_file(proxy_path)\n        raise SoniloError(\"Sonilo video proxy generation timed out\") from exc\n    except OSError as exc:\n        _remove_file(proxy_path)\n        raise SoniloError(\"failed to run FFmpeg for Sonilo video proxy\") from exc\n    if result.returncode != 0:\n        _remove_file(proxy_path)\n        detail = (result.stderr or \"\").strip().replace(\"\\n\", \" \")[-500:]\n        raise SoniloError(f\"failed to generate Sonilo video proxy: {detail}\")\n    proxy_size = os.path.getsize(proxy_path) if os.path.isfile(proxy_path) else 0\n    if proxy_size <= 0 or proxy_size > MAX_PROXY_BYTES:\n        _remove_file(proxy_path)\n        raise SoniloError(\"Sonilo video proxy is empty or exceeds the 300 MB limit\")\n    logger.info(\n        f\"Sonilo video proxy prepared: source={video_path}, size={proxy_size} bytes\"\n    )\n    return proxy_path\n\n\ndef _parse_event(raw_line: bytes) -> dict[str, Any]:","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/harry0703/MoneyPrinterTurbo/blob/1f9f19c2021a68d04df228f33e9099a0c947f6f8/app/services/sonilo.py#L167-L203","documentation":"Raised when the FFmpeg subprocess that builds the downscale/re-encode proxy of the source video exceeds the hard-coded 600-second timeout in subprocess.run, producing a subprocess.TimeoutExpired that is wrapped as SoniloError. The partial proxy file is deleted before the raise. This is a local resource problem, not a Sonilo API failure.","triggerScenarios":"Uploading a long (near the 360-second limit) high-bitrate video where the proxy encode cannot finish in 600 seconds; running on a starved CPU (shared CI runner, low-core VPS) so even moderate encodes stall; FFmpeg deadlocked on a corrupted or pathological input file.","commonSituations":"4K/60fps source clips on a 1-2 vCPU server; other heavy jobs competing for CPU during task runs; an input video with unusual codecs (for example 10-bit HEVC) that decodes very slowly without hardware acceleration.","solutions":["Check CPU utilization during proxy generation; if the box is saturated, reduce concurrent tasks or move to a beefier machine.","Pre-transcode or downscale very large sources before submitting the task, or lower the source resolution and bitrate.","Verify the source file plays cleanly with ffprobe/ffmpeg; a corrupt input can make FFmpeg spin.","If encodes are legitimately long on this hardware, raise the timeout=600 argument in app/services/sonilo.py:180 to a value that fits your worst case."],"exampleFix":"# before\nresult = subprocess.run(command, capture_output=True, text=True, timeout=600, check=False)\n# after (only if hardware legitimately needs longer)\nresult = subprocess.run(command, capture_output=True, text=True, timeout=900, check=False)","handlingStrategy":"validation","validationCode":"import subprocess\n\ndef probe_duration_seconds(video_path: str) -> float:\n    out = subprocess.run(\n        [\"ffprobe\", \"-v\", \"error\", \"-show_entries\", \"format=duration\",\n         \"-of\", \"default=nw=1:nk=1\", video_path],\n        capture_output=True, text=True, check=True,\n    )\n    return float(out.stdout.strip())\n\n# reject inputs that cannot possibly finish inside the encode window\nif probe_duration_seconds(video) > sonilo.MAX_VIDEO_DURATION_SECONDS:\n    raise ValueError(\"video too long for Sonilo proxy generation\")","typeGuard":null,"tryCatchPattern":"try:\n    proxy = generate_video_proxy(video)\nexcept SoniloError as exc:\n    if \"timed out\" in str(exc):\n        # local CPU-bound failure: retrying on the same loaded box rarely helps\n        mark_task_for_retry_after_cooldown()\n    raise","preventionTips":["Size the worker host for the longest accepted video (360 s) at your worst encode speed, and cap concurrent proxy jobs to one per core.","Pre-validate duration and resolution with ffprobe at upload time instead of failing during generation."],"tags":["ffmpeg","subprocess","timeout","video","sonilo"],"backgroundTag":null,"analyzedSha":"1f9f19c2021a68d04df228f33e9099a0c947f6f8","analyzedAt":"2026-08-14T19:41:05.568Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}