=== Factorize Vision ===
Contributors: webyoungstown
Tags: woocommerce, ai, ollama, product-images, video
Requires at least: 6.2
Tested up to: 6.7
Stable tag: 1.2.1
Requires PHP: 7.4
License: Factorize License (proprietary)
License URI: https://factorize.webyoungstown.com/license/

Turn a walkthrough video into cropped product photos, names, and price suggestions with a local Ollama vision model. Nothing leaves your network.

== Description ==

Photographing inventory one item at a time is the slowest part of running a liquidation, bin, or open-box store. Factorize Vision replaces it with a walk: film your shelf with a phone (a slow pan, 2-3 seconds on each item), drop the video on the Vision Intake admin page, and a vision model running on your own Ollama server finds each product, crops it out of the frame, suggests a retail name and a typical US retail price, and even critiques your filming so the next pass is better. Each detection becomes a Media Library photo and a draft WooCommerce product in one click each. There is no cloud API and no API key — frames travel from your browser to your WordPress site to your own Ollama box and nowhere else.

= Features =

* One-screen video intake page in wp-admin (Factorize > Vision Intake) — pick a video, press Analyze.
* Fully local AI: frames go browser -> your WordPress site -> your own Ollama server. No third-party service, no keys, no uploads off your network.
* The video file itself never leaves the browser — frames are captured to a canvas locally and only downscaled JPEG stills are sent.
* Automatic server and model detection: checks your Ollama server on page load, uses your configured model when installed, and otherwise falls back to any installed vision-family model (qwen-vl, llava, moondream, minicpm-v, and similar).
* One-click model bootstrap: when the server has no vision model at all, a "Prepare model" button pulls the lightweight moondream model (about 1.7 GB) for you.
* Smart frame sampling: configurable capture interval, frame cap, and downscale size keep model calls fast and predictable — with a built-in workaround for phone/MediaRecorder webm files that report infinite duration.
* Structured per-frame analysis: the model returns strict JSON — is there a product, its retail name, a condition or visibility warning, an estimated US retail price, a bounding box, and a blur flag.
* Auto-cropped product photos: each product is cropped from its best frame using the model's bounding box, with padding, whether the model answers in pixels or percentages.
* Best-shot selection: frames are grouped by product name and the sharpest, largest view of each product wins — one card per product, not per frame.
* Suggested retail price on every product card, labeled as an industry-typical estimate.
* Condition warnings surfaced per product ("box crushed", "label obscured") straight from the model.
* A filming coach that scores the video itself: too fast (share of blurry frames), possibly rushed (products seen in only one frame), lingering (products on screen too long), gaps where no product was visible, and failed frames — or an all-clear when the pass was clean.
* Live progress: frame thumbnails appear as they are captured, with a per-frame status line during analysis.
* Save any detection to the Media Library as a JPEG attachment (with generated thumbnails and metadata) in one click.
* Create a draft WooCommerce product in one click: name, suggested price, and the saved photo as the featured image, with a direct "edit it" link. Drafts only — nothing is ever auto-published.
* Warm-model handling: a configurable keep_alive keeps the model in memory between calls, and a generous per-call timeout absorbs the cold first load.
* Nonce and capability checks on every AJAX action (manage_woocommerce for analysis and drafts, upload_files for media saves).
* Clean uninstall: removes only the plugin's own options — your media and products are never touched.

* Whole-video coverage: one frame slot per interval across the entire duration (a 60-second video is about 25 frames), not just the opening seconds — with a one-click fallback to a fixed clip budget and an estimate line that says exactly how many seconds, frames, calls, and tokens a run will take.
* Several products per frame: the model lists every identifiable product in a shelf, bin, or table shot; each gets its own crop, row, price, warning, and vote, and sightings of the same item across frames collapse into one review row.
* Count mode: when you need everything on the shelf rather than a curated list, switch the Mode selector to Count. Frames are sampled denser (1.25s) and analyzed as overlapping tiles so dense shelves do not overwhelm the model; sightings pool across the whole video by fuzzy name with brands kept apart, and every product shows its units - the highest number of that product visible in any single frame. Unnamed sightings stay as numbered "Item" rows instead of being dropped, and the CSV carries row numbers, units, and frames seen.
* Intensity meter: choose 1 (Quick), 2 (Cross-check), or 3 (Consensus) analysis passes per frame. Extra passes re-ask the model at different temperatures and vote — majority on product/blur, name groups elect a leader, median price, best bounding box — with disagreements flagged for human review. Targets: ~80% at level 1 up to 95-99% at level 3 with review.
* Factorize tokens: the AI feature is metered by model calls — 1 token = 1 call (a frame, tile, or pass). Every store gets 50 tokens a month included; the page shows used/left, the estimate says what a run costs and warns when it exceeds what is left, and a run that hits the cap stops cleanly with the rows it already found and the number to call for more (330-519-9231). Every other Factorize plugin is free.
* Model-token meter: a live count of the words the model reads and writes per call, a pre-run estimate, and per-run totals (model tokens in/out, model calls, wall time) — for capacity planning; model tokens are local compute on your own hardware, never billed.
* Run analytics panel: the last 50 runs with intensity, frames, calls, tokens, time, products found, consensus %, blurry frames, and errors, so you can measure exactly what each intensity level buys on your hardware.
* Adaptive frame selection: 3 candidate frames are sampled per slot and only the sharpest of each trio (gradient-energy scored) is analyzed — the same model cost buys visibly better frames on hand-held video.
* A review layer before anything touches the store: every detection lands in an editable table (name, price, include-checkbox) — nothing is created until you approve it.
* Export to spreadsheet only: one click downloads the reviewed rows as a CSV (name, price, warning, duplicate match, frame time) without adding any products.
* Inventory duplicate check: detected names are fuzzy-matched against your existing catalog (tolerant of imperfect titles); likely duplicates are flagged with a match percentage, linked to the existing product, and left unchecked for you to decide.
* Batch add: approved rows become draft WooCommerce products (image + name + price) in one click, and stay drafts until you publish them.

= Works standalone, better together =

Factorize is a modular WooCommerce toolkit for liquidation, bin, discount, and open-box stores, built and battle-tested on a real 950-product store. Every plugin works completely standalone; any of them alone stands up the shared "Factorize" admin hub, and together they fill it with category tabs (Insights / Selling / Customers / Storefront). Factorize Vision alone creates the hub and registers its card under Insights, with a status line showing which vision server it is pointed at.

= Configuration =

All settings live in code-level configuration — defaults merged with the factorize-vision_options WordPress option (override any subset of keys), then passed through the factorize-vision_config filter. The legacy empire-vision-intake_options option is still honored. There is no settings screen yet; set the option with WP-CLI or use the filter in a small plugin.

Keys and defaults:

* ollama_host (192.168.1.6) — LAN address of the Ollama server.
* ollama_port (11434) — Ollama port.
* model (qwen2.5vl:7b) — preferred vision model, used when installed.
* fallback_model (moondream) — offered for download when the server has no vision model.
* frame_interval (2.5) — seconds between captured frames.
* max_frames (8) — clip budget when "Analyze the whole video" is unticked; each frame is one model call per pass.
* whole_video (true) — analyze the entire duration by default.
* whole_video_cap (60) — safety cap on frame slots for very long videos.
* frame_size (512) — longest side of a captured frame in pixels; smaller is much faster.
* intensity (1) — default analysis passes per frame (1-3); also selectable per run on the page.
* monthly_allowance (50) — Factorize tokens included per calendar month (1 token = 1 model call).
* allowance_contact (330-519-9231) — who to contact for more tokens; shown with the meter.
* allowance_unlimited (false) — lift the monthly cap on a site with an arrangement for more.
* mode (catalog) — default mode: catalog (one row per product) or count (one row per physical unit).
* count_interval (1.25) — seconds between frame slots in count mode.
* count_tiles (2) — overlapping tiles per frame in count mode (1-4); calls scale with tiles.
* count_max_items (15) — cap on units the model may list per tile.
* num_ctx (4096) — context window requested per call; keeps a 128k-context model from allocating tens of GB of KV cache on CPU.
* num_predict (700) — hard cap on reply tokens so a rambling reply cannot eat the timeout.
* keep_alive (15m) — how long Ollama keeps the model in memory between calls.
* timeout (600) — per-call timeout in seconds; the first call after idle reloads the model.

Example: wp option update factorize-vision_options '{"ollama_host":"10.0.0.5"}' --format=json

= Roadmap =

Planned — not yet in this release:

* Barcode / UPC lookup with catalog matching
* Live camera mode
* Auto-publish pipeline with review queue
* GPU batch mode
* Background removal
* AI condition grading

== Installation ==

1. Upload the factorize-vision folder to /wp-content/plugins/, or install the zip via Plugins > Add New, then activate. WooCommerce should be active — the page requires the manage_woocommerce capability, and drafts are WooCommerce products.
2. A "Factorize" menu appears in the admin sidebar (this plugin alone creates the hub). Open Factorize > Vision Intake.
3. Point the plugin at your Ollama server. The default is 192.168.1.6:11434 — if yours differs, run: wp option update factorize-vision_options '{"ollama_host":"YOUR_HOST","ollama_port":11434}' --format=json, or use the factorize-vision_config filter.
4. The page checks the server on load. If it is reachable but has no vision model, click "Prepare model" — it downloads moondream (about 1.7 GB) once; this can take several minutes.
5. Film your products with a phone — a slow pan, pausing 2-3 seconds on each item — choose the file, and click "Analyze video".
6. For each detected product: "Save image to library", then "Create draft product", then follow the edit link to review and publish.

== Frequently Asked Questions ==

= Does it work without the other Factorize plugins? =

Yes. Factorize Vision is fully standalone and by itself stands up the shared Factorize admin hub with its Vision Intake screen. WooCommerce, however, is effectively required: the page and its analysis actions require the manage_woocommerce capability, and one-click drafts create WooCommerce products.

= Does my video or any image leave my server? =

No. The video file never leaves your browser — frames are captured locally to a canvas. Captured frames are posted to your own WordPress site (admin-ajax), which forwards them to the Ollama server you configure. There is no third-party API, no account, and no key.

= What do I need to run the AI? =

An Ollama server reachable from your WordPress server, typically a box on your LAN. The default model is qwen2.5vl:7b; if it is not installed, the plugin uses any installed vision-family model, and offers a one-click download of moondream (about 1.7 GB) as a last resort. On CPU-only hardware a frame takes roughly 1-3 minutes to analyze, which is why the default caps analysis at 8 frames.

= How do I change the Ollama address, model, or frame settings? =

Via the factorize-vision_options option (override any subset of keys) or the factorize-vision_config filter — there is no settings screen yet. For example: wp option update factorize-vision_options '{"model":"llava:13b","max_frames":12}' --format=json

= Where do the photos and products go? =

Saved photos become JPEG attachments in your Media Library, with normal WordPress thumbnails and metadata. Products are created as draft WooCommerce simple products with the name, suggested price, and the photo as the featured image — nothing is published without you.

= What is a Factorize token, and what happens when I run out? =

One token is one call to the vision model — a frame, a tile, or a pass. Every store gets 50 a month; the intake page shows used/left and the estimate line tells you what a run will cost before you start. If a run reaches the cap it stops cleanly, keeps the rows it already found, and shows the number to text or call for more (330-519-9231). The count resets each calendar month. Model tokens (the words the model reads and writes) are reported separately for capacity planning and are never billed.

= Why does the first frame take minutes? =

Ollama loads the model into memory on the first call after idle, which can take several minutes on modest hardware. The per-call timeout defaults to 420 seconds to absorb this, and keep_alive (default 15m) keeps the model warm between frames so later frames are much faster.

== Screenshots ==

1. The Vision Intake screen: server status line, model in use, and the video picker with the Analyze button.
2. Frame thumbnails appearing as the browser samples the video, with the per-frame progress line.
3. The Video feedback panel: pacing coaching (too fast / rushed / lingering / gaps) and per-product condition warnings.
4. A detected product card: auto-cropped photo, suggested retail price, warning badge, and the Save / Create draft buttons.
5. The Factorize hub with the Vision card in the Insights tab, showing the configured vision server.

== Changelog ==

= 1.2.0 =
* Count mode: denser frames, overlapping tiles, whole-video name pooling with a brand rule, and a per-product units count (highest count in one frame); unnamed sightings kept as numbered rows.
* Truncated model replies are salvaged (every complete entry kept) instead of failing the frame; near-identical repeated boxes are dropped server-side.
* Whole-video coverage by default (one slot per interval across the full duration, capped) with a clip-budget fallback and a duration-aware estimate line.
* Several products per frame: per-frame product lists, one crop/row/vote per product, sightings pooled across frames.
* Intensity meter: 1-3 temperature-varied passes per frame with consensus voting; per-row "N/N passes agree" and disagreement callouts.
* Token system: live token meter, pre-run estimate, and per-run in/out totals from Ollama's token counts.
* Run analytics panel: last 50 runs with tokens, time, consensus, products, blur, and errors.
* Adaptive frame selection: sharpest-of-3 candidate sampling per slot (gradient-energy scored).
* Duplicate check returns up to three ranked catalog candidates per name (coverage-scored matcher, 100% brand+type family accuracy and 0 false flags on the offline eval).
* Per-frame retry on busy servers; per-call timeout raised to 600s.
* Requests a 4k context window (num_ctx) and caps reply tokens (num_predict): a 128k-context vision model no longer allocates tens of GB on CPU — qwen2.5vl:7b drops from 52GB to 15GB and stays GPU-resident, roughly 3x faster per frame with no cold reloads.
* Brand-only fragment guard: names made only of brand / product-line / filler words ("M18 FUEL") are quarantined in the review table and never matched against inventory.

= 1.1.0 =
* Review layer: editable approval table before anything is added to the store.
* Export-to-CSV (spreadsheet only) path.
* Inventory duplicate detection with fuzzy title matching.
* Batch draft creation for approved rows.
* HEVC/iPhone .MOV support notes; stray-seek frame capture fix.

= 1.0.0 =
* Initial release.
* Video-to-product intake: in-browser frame capture, local Ollama vision analysis, auto-cropped product photos.
* Suggested retail names and industry-typical price estimates per product.
* Filming coach: blur, pacing, gap, and condition feedback on every pass.
* One-click save to Media Library and one-click draft WooCommerce product.
* Automatic model detection with one-click moondream bootstrap when the server has no vision model.
* Factorize admin hub with the Vision Intake screen under Insights.
