affaan-m/ECC · error · MediaToolUnavailable
ffmpeg is required for temporal/style feature extraction
Error message
ffmpeg is required for temporal/style feature extraction
What it means
Dependency guard in _run_ffmpeg_features: the ffmpeg binary was not found on PATH, so timestamped luma/saturation/scene-change features cannot be extracted from the media. The message fires before any probing runs.
Solutions
- Install ffmpeg (apt install ffmpeg / brew install ffmpeg / conda install ffmpeg)
- Ensure the ffmpeg binary's directory is on PATH for the process running the workflow
- Pin ffmpeg in your Dockerfile/CI setup so it is always present
Example fix
// before $ python workflow.py --config cfg.json # MediaToolUnavailable // after $ sudo apt-get update && sudo apt-get install -y ffmpeg $ which ffmpeg && python workflow.py --config cfg.json
Defensive patterns
Strategy: fallback
Validate before calling
import shutil
if shutil.which("ffmpeg") is None:
raise SystemExit("ffmpeg not found on PATH; install it before running tasteforge") Type guard
def has_ffmpeg() -> bool:
import shutil
return shutil.which("ffmpeg") is not None Try / catch
try:
features = probe_media(path)
except MediaToolUnavailable:
features = fallback_features_without_temporal_style(path) # or abort with clear message Prevention
- Bake ffmpeg into your container/CI image
- Check `which ffmpeg` in entrypoint scripts before running the workflow
- Keep PATH consistent between interactive shells and service contexts
When it happens
Trigger: probe_media -> _run_ffmpeg_features is invoked on a media file while shutil.which('ffmpeg') returns None (ffmpeg not installed or not on PATH of the calling process).
Common situations: Minimal Docker images or CI runners without ffmpeg; virtualenv/conda environments lacking the binary; PATH differences between interactive shell and cron/systemd.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- ENOENT
- ffprobe is required for reference probing
- ${capability.reason}: ${capability.action}
- Crop must fit within normalized image coordinates
- Decoder produced a truncated frame
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/44561b7103466e35.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/tasteforge/workflow.py:351
style_samples = []
scene_changes = []
for record in records:
if "luma_raw" in record:
style_samples.append({
"time": round(record["time"], 6),
"luma": round(record["luma_raw"] / 255.0, 6),
"saturation": round(record.get("saturation_raw", 0.0) / 100.0, 6),
"hue": record.get("hue"),
})
if record.get("scene_score", 0.0) >= scene_threshold:
scene_changes.append(round(record["time"], 6))
return {"style_samples": style_samples, "scene_changes": scene_changes}
def _run_ffmpeg_features(path: Path) -> dict[str, Any]:
ffmpeg = shutil.which("ffmpeg")
if not ffmpeg:
raise MediaToolUnavailable("ffmpeg is required for temporal/style feature extraction")
filters = (
"scale=320:-2,"
"select='not(mod(n\\,12))+gt(scene\\,0.30)',"
"signalstats,metadata=print:file=-"
)
result = subprocess.run(
[ffmpeg, "-v", "error", "-i", str(path), "-vf", filters,
"-an", "-vsync", "0", "-f", "null", "-"],
check=True,
capture_output=True,
text=True,
)
return parse_feature_output(result.stderr + "\n" + result.stdout)
def probe_media(path: Path) -> dict[str, Any]:
"""Probe local media and extract timestamped style/temporal features."""
ffprobe = shutil.which("ffprobe")View on GitHub (pinned to 8321021c54)