diff --git a/.memory/worklog.json b/.memory/worklog.json index cbd7b0c..a3280c9 100644 --- a/.memory/worklog.json +++ b/.memory/worklog.json @@ -1,19 +1,5 @@ { "entries": [ - { - "files_changed": 2, - "hash": "684930d", - "message": "auto-save 2026-05-12 18:57 (~2)", - "ts": "2026-05-12T18:57:53+08:00", - "type": "commit" - }, - { - "files_changed": 1, - "hash": "50d6390", - "message": "auto-save 2026-05-12 19:03 (~1)", - "ts": "2026-05-12T19:03:35+08:00", - "type": "commit" - }, { "files_changed": 3, "hash": "67bbdae", @@ -3345,6 +3331,19 @@ "type": "session-heartbeat", "message": "Codex 会话活跃 · 最近命令:codex · 1 项未提交变更 · 最近提交:auto-save 2026-05-14 06:44 (~4)", "files_changed": 1 + }, + { + "ts": "2026-05-14T06:50:10+08:00", + "type": "commit", + "message": "auto-save 2026-05-14 06:49 (~1)", + "hash": "9546d5f", + "files_changed": 1 + }, + { + "ts": "2026-05-13T22:53:14Z", + "type": "session-heartbeat", + "message": "Claude 会话活跃 · 最近命令:claude · 1 项未提交变更 · 最近提交:auto-save 2026-05-14 06:49 (~1)", + "files_changed": 1 } ] } diff --git a/api/main.py b/api/main.py index 8b81f6c..4dc8077 100644 --- a/api/main.py +++ b/api/main.py @@ -23,6 +23,10 @@ load_dotenv() JOBS_DIR = Path(os.getenv("JOBS_DIR", "./jobs")).resolve() JOBS_DIR.mkdir(parents=True, exist_ok=True) CORS_ORIGINS = [o.strip() for o in os.getenv("CORS_ORIGINS", "http://localhost:4290").split(",") if o.strip()] +PRODUCT_LIBRARY_DIR = Path( + os.getenv("PRODUCT_LIBRARY_DIR", Path(__file__).resolve().parent / "product_library" / "skg-products") +).resolve() +PRODUCT_LIBRARY_MANIFEST = PRODUCT_LIBRARY_DIR / "manifest.json" LLM_BASE_URL = os.getenv("LLM_BASE_URL", "").strip() LLM_API_KEY = os.getenv("LLM_API_KEY", "").strip() @@ -214,6 +218,24 @@ class SubjectAsset(BaseModel): created_at: float = 0.0 +class ProductLibraryItem(BaseModel): + id: str + handle: str + title: str + product_type: str = "" + image_type: str = "gallery" + image_index: int = 0 + filename: str + url: str + width: int = 0 + height: int = 0 + source_path: str = "" + white_score: float = 0.0 + near_white_score: float = 0.0 + has_people: bool = False + tags: list[str] = Field(default_factory=list) + + class KeyElement(BaseModel): """关键帧里识别 / 用户提取的元素 · 多次提取累积多张图,让用户挑选满意的""" id: str # uuid hex 8 @@ -368,6 +390,35 @@ def storyboard_ref_path(job_id: str, ref: dict | None) -> Path | None: return None +def load_product_library_items() -> list[ProductLibraryItem]: + if not PRODUCT_LIBRARY_MANIFEST.exists(): + return [] + try: + data = json.loads(PRODUCT_LIBRARY_MANIFEST.read_text(encoding="utf-8")) + return [ProductLibraryItem(**item) for item in data.get("items", [])] + except Exception as e: + raise HTTPException(500, f"product library manifest invalid: {e}") + + +def find_product_library_item(product_id: str) -> ProductLibraryItem: + product_id = product_id.strip() + for item in load_product_library_items(): + if item.id == product_id: + return item + raise HTTPException(404, "product library item not found") + + +def product_library_file(item: ProductLibraryItem) -> Path: + p = (PRODUCT_LIBRARY_DIR / item.filename).resolve() + try: + p.relative_to(PRODUCT_LIBRARY_DIR) + except ValueError: + raise HTTPException(400, "invalid product library path") + if not p.exists(): + raise HTTPException(404, "product library image missing") + return p + + def storyboard_ref_url(job_id: str, ref: dict | None) -> str: if not ref: return "" @@ -2783,6 +2834,25 @@ def get_storyboard_video(job_id: str, video_id: str): return FileResponse(p, media_type="video/mp4") +class CopyProductLibraryAssetReq(BaseModel): + product_id: str + + +@app.get("/product-library/skg", response_model=list[ProductLibraryItem]) +def list_skg_product_library() -> list[ProductLibraryItem]: + """内置 SKG 白底产品图库。来源是本地筛选后的产品图 manifest。""" + return load_product_library_items() + + +@app.get("/product-library/skg/images/{filename}") +def get_skg_product_library_image(filename: str): + items = load_product_library_items() + item = next((x for x in items if Path(x.filename).name == filename), None) + if not item: + raise HTTPException(404, "product library image not found") + return FileResponse(product_library_file(item), media_type="image/jpeg") + + @app.post("/jobs/{job_id}/assets") async def upload_storyboard_asset(job_id: str, file: UploadFile = File(...)) -> dict: if job_id not in JOBS: @@ -2813,6 +2883,32 @@ async def upload_storyboard_asset(job_id: str, file: UploadFile = File(...)) -> } +@app.post("/jobs/{job_id}/assets/product-library") +def copy_product_library_asset(job_id: str, req: CopyProductLibraryAssetReq) -> dict: + if job_id not in JOBS: + raise HTTPException(404, "job not found") + item = find_product_library_item(req.product_id) + src = product_library_file(item) + asset_id = uuid.uuid4().hex[:12] + out_dir = job_dir(job_id) / "assets" + out_dir.mkdir(parents=True, exist_ok=True) + out = out_dir / f"{asset_id}.jpg" + try: + img = Image.open(src).convert("RGB") + img.thumbnail((1600, 1600), Image.Resampling.LANCZOS) + img.save(out, "JPEG", quality=94) + except Exception as e: + raise HTTPException(400, f"product library copy failed: {e}") + label = f"产品融合 · {item.title} #{item.image_index}" + return { + "kind": "asset", + "frame_idx": -1, + "element_id": asset_id, + "cutout_id": asset_id, + "label": label, + } + + @app.get("/jobs/{job_id}/assets/{asset_id}.jpg") def get_storyboard_asset(job_id: str, asset_id: str): p = job_dir(job_id) / "assets" / f"{asset_id}.jpg" diff --git a/api/product_library/skg-products/images/g7-pro-fold-neck-massager-01.jpg b/api/product_library/skg-products/images/g7-pro-fold-neck-massager-01.jpg new file mode 100644 index 0000000..2719322 Binary files /dev/null and b/api/product_library/skg-products/images/g7-pro-fold-neck-massager-01.jpg differ diff --git a/api/product_library/skg-products/images/g7-pro-fold-neck-massager-05.jpg b/api/product_library/skg-products/images/g7-pro-fold-neck-massager-05.jpg new file mode 100644 index 0000000..eec5cf7 Binary files /dev/null and b/api/product_library/skg-products/images/g7-pro-fold-neck-massager-05.jpg differ diff --git a/api/product_library/skg-products/images/g7-pro-neck-massager-01.jpg b/api/product_library/skg-products/images/g7-pro-neck-massager-01.jpg new file mode 100644 index 0000000..ed873e9 Binary files /dev/null and b/api/product_library/skg-products/images/g7-pro-neck-massager-01.jpg differ diff --git a/api/product_library/skg-products/images/g7-pro-neck-massager-02.jpg b/api/product_library/skg-products/images/g7-pro-neck-massager-02.jpg new file mode 100644 index 0000000..13ee311 Binary files /dev/null and b/api/product_library/skg-products/images/g7-pro-neck-massager-02.jpg differ diff --git a/api/product_library/skg-products/images/g7-pro-neck-massager-04.jpg b/api/product_library/skg-products/images/g7-pro-neck-massager-04.jpg new file mode 100644 index 0000000..7db88e8 Binary files /dev/null and b/api/product_library/skg-products/images/g7-pro-neck-massager-04.jpg differ diff --git a/api/product_library/skg-products/images/g7-pro-neck-massager-07.jpg b/api/product_library/skg-products/images/g7-pro-neck-massager-07.jpg new file mode 100644 index 0000000..ef4c3b5 Binary files /dev/null and b/api/product_library/skg-products/images/g7-pro-neck-massager-07.jpg differ diff --git a/api/product_library/skg-products/images/g7-pro-neck-massager-11.jpg b/api/product_library/skg-products/images/g7-pro-neck-massager-11.jpg new file mode 100644 index 0000000..1b61228 Binary files /dev/null and b/api/product_library/skg-products/images/g7-pro-neck-massager-11.jpg differ diff --git a/api/product_library/skg-products/images/g7-pro-neck-massager-12.jpg b/api/product_library/skg-products/images/g7-pro-neck-massager-12.jpg new file mode 100644 index 0000000..78de5a9 Binary files /dev/null and b/api/product_library/skg-products/images/g7-pro-neck-massager-12.jpg differ diff --git a/api/product_library/skg-products/images/h7-ultra-05.jpg b/api/product_library/skg-products/images/h7-ultra-05.jpg new file mode 100644 index 0000000..cfbadb6 Binary files /dev/null and b/api/product_library/skg-products/images/h7-ultra-05.jpg differ diff --git a/api/product_library/skg-products/images/h7-ultra-11.jpg b/api/product_library/skg-products/images/h7-ultra-11.jpg new file mode 100644 index 0000000..37812b7 Binary files /dev/null and b/api/product_library/skg-products/images/h7-ultra-11.jpg differ diff --git a/api/product_library/skg-products/images/k5-pro-neck-massager-02.jpg b/api/product_library/skg-products/images/k5-pro-neck-massager-02.jpg new file mode 100644 index 0000000..051f186 Binary files /dev/null and b/api/product_library/skg-products/images/k5-pro-neck-massager-02.jpg differ diff --git a/api/product_library/skg-products/images/skg-flex-massager-h7-ultra-e-01.jpg b/api/product_library/skg-products/images/skg-flex-massager-h7-ultra-e-01.jpg new file mode 100644 index 0000000..7e23182 Binary files /dev/null and b/api/product_library/skg-products/images/skg-flex-massager-h7-ultra-e-01.jpg differ diff --git a/api/product_library/skg-products/images/skg-flex-massager-h7-ultra-e-06.jpg b/api/product_library/skg-products/images/skg-flex-massager-h7-ultra-e-06.jpg new file mode 100644 index 0000000..9551de4 Binary files /dev/null and b/api/product_library/skg-products/images/skg-flex-massager-h7-ultra-e-06.jpg differ diff --git a/api/product_library/skg-products/images/skg-g7-pro-fold-golden-neck-massager-02.jpg b/api/product_library/skg-products/images/skg-g7-pro-fold-golden-neck-massager-02.jpg new file mode 100644 index 0000000..2c82d49 Binary files /dev/null and b/api/product_library/skg-products/images/skg-g7-pro-fold-golden-neck-massager-02.jpg differ diff --git a/api/product_library/skg-products/images/skg-g7-pro-fold-golden-neck-massager-03.jpg b/api/product_library/skg-products/images/skg-g7-pro-fold-golden-neck-massager-03.jpg new file mode 100644 index 0000000..e3a2db1 Binary files /dev/null and b/api/product_library/skg-products/images/skg-g7-pro-fold-golden-neck-massager-03.jpg differ diff --git a/api/product_library/skg-products/images/skg-h5-mini-cordless-shiatsu-neck-and-shoulder-massager-with-heat-01.jpg b/api/product_library/skg-products/images/skg-h5-mini-cordless-shiatsu-neck-and-shoulder-massager-with-heat-01.jpg new file mode 100644 index 0000000..b925676 Binary files /dev/null and b/api/product_library/skg-products/images/skg-h5-mini-cordless-shiatsu-neck-and-shoulder-massager-with-heat-01.jpg differ diff --git a/api/product_library/skg-products/images/skg-h5-mini-cordless-shiatsu-neck-and-shoulder-massager-with-heat-08.jpg b/api/product_library/skg-products/images/skg-h5-mini-cordless-shiatsu-neck-and-shoulder-massager-with-heat-08.jpg new file mode 100644 index 0000000..e0e046b Binary files /dev/null and b/api/product_library/skg-products/images/skg-h5-mini-cordless-shiatsu-neck-and-shoulder-massager-with-heat-08.jpg differ diff --git a/api/product_library/skg-products/images/skg-h5-mini-cordless-shiatsu-neck-and-shoulder-massager-with-heat-09.jpg b/api/product_library/skg-products/images/skg-h5-mini-cordless-shiatsu-neck-and-shoulder-massager-with-heat-09.jpg new file mode 100644 index 0000000..0a42c20 Binary files /dev/null and b/api/product_library/skg-products/images/skg-h5-mini-cordless-shiatsu-neck-and-shoulder-massager-with-heat-09.jpg differ diff --git a/api/product_library/skg-products/images/skg-knee-massager-ws500-01.jpg b/api/product_library/skg-products/images/skg-knee-massager-ws500-01.jpg new file mode 100644 index 0000000..5ed97de Binary files /dev/null and b/api/product_library/skg-products/images/skg-knee-massager-ws500-01.jpg differ diff --git a/api/product_library/skg-products/images/skg-knee-massager-ws500-03.jpg b/api/product_library/skg-products/images/skg-knee-massager-ws500-03.jpg new file mode 100644 index 0000000..50b1171 Binary files /dev/null and b/api/product_library/skg-products/images/skg-knee-massager-ws500-03.jpg differ diff --git a/api/product_library/skg-products/images/skg-knee-massager-ws500-04.jpg b/api/product_library/skg-products/images/skg-knee-massager-ws500-04.jpg new file mode 100644 index 0000000..981823a Binary files /dev/null and b/api/product_library/skg-products/images/skg-knee-massager-ws500-04.jpg differ diff --git a/api/product_library/skg-products/images/skg-knee-massager-ws500-05.jpg b/api/product_library/skg-products/images/skg-knee-massager-ws500-05.jpg new file mode 100644 index 0000000..7432688 Binary files /dev/null and b/api/product_library/skg-products/images/skg-knee-massager-ws500-05.jpg differ diff --git a/api/product_library/skg-products/images/skg-neck-and-shoulder-massager-hs500-2-01.jpg b/api/product_library/skg-products/images/skg-neck-and-shoulder-massager-hs500-2-01.jpg new file mode 100644 index 0000000..1302ac6 Binary files /dev/null and b/api/product_library/skg-products/images/skg-neck-and-shoulder-massager-hs500-2-01.jpg differ diff --git a/api/product_library/skg-products/images/skg-neck-and-shoulder-massager-hs500-2-06.jpg b/api/product_library/skg-products/images/skg-neck-and-shoulder-massager-hs500-2-06.jpg new file mode 100644 index 0000000..4a22c62 Binary files /dev/null and b/api/product_library/skg-products/images/skg-neck-and-shoulder-massager-hs500-2-06.jpg differ diff --git a/api/product_library/skg-products/images/skg-neck-and-shoulder-massager-hs500-2-10.jpg b/api/product_library/skg-products/images/skg-neck-and-shoulder-massager-hs500-2-10.jpg new file mode 100644 index 0000000..0487aaa Binary files /dev/null and b/api/product_library/skg-products/images/skg-neck-and-shoulder-massager-hs500-2-10.jpg differ diff --git a/api/product_library/skg-products/images/skg-neck-and-shoulder-massager-hs500-2-11.jpg b/api/product_library/skg-products/images/skg-neck-and-shoulder-massager-hs500-2-11.jpg new file mode 100644 index 0000000..e57f0b1 Binary files /dev/null and b/api/product_library/skg-products/images/skg-neck-and-shoulder-massager-hs500-2-11.jpg differ diff --git a/api/product_library/skg-products/images/skg-neck-and-shoulder-massager-hs500-2-12.jpg b/api/product_library/skg-products/images/skg-neck-and-shoulder-massager-hs500-2-12.jpg new file mode 100644 index 0000000..41e0788 Binary files /dev/null and b/api/product_library/skg-products/images/skg-neck-and-shoulder-massager-hs500-2-12.jpg differ diff --git a/api/product_library/skg-products/images/skg-neck-massager-gs500-n-01.jpg b/api/product_library/skg-products/images/skg-neck-massager-gs500-n-01.jpg new file mode 100644 index 0000000..2b43442 Binary files /dev/null and b/api/product_library/skg-products/images/skg-neck-massager-gs500-n-01.jpg differ diff --git a/api/product_library/skg-products/images/skg-neck-massager-gs500-n-03.jpg b/api/product_library/skg-products/images/skg-neck-massager-gs500-n-03.jpg new file mode 100644 index 0000000..aae81c1 Binary files /dev/null and b/api/product_library/skg-products/images/skg-neck-massager-gs500-n-03.jpg differ diff --git a/api/product_library/skg-products/images/skg-neck-massager-gs500-n-04.jpg b/api/product_library/skg-products/images/skg-neck-massager-gs500-n-04.jpg new file mode 100644 index 0000000..e79dd72 Binary files /dev/null and b/api/product_library/skg-products/images/skg-neck-massager-gs500-n-04.jpg differ diff --git a/api/product_library/skg-products/images/skg-neck-massager-gs500-n-05.jpg b/api/product_library/skg-products/images/skg-neck-massager-gs500-n-05.jpg new file mode 100644 index 0000000..78ac00b Binary files /dev/null and b/api/product_library/skg-products/images/skg-neck-massager-gs500-n-05.jpg differ diff --git a/api/product_library/skg-products/images/skg-vs500-back-and-neck-massager-01.jpg b/api/product_library/skg-products/images/skg-vs500-back-and-neck-massager-01.jpg new file mode 100644 index 0000000..8e823cb Binary files /dev/null and b/api/product_library/skg-products/images/skg-vs500-back-and-neck-massager-01.jpg differ diff --git a/api/product_library/skg-products/images/skg-vs500-back-and-neck-massager-03.jpg b/api/product_library/skg-products/images/skg-vs500-back-and-neck-massager-03.jpg new file mode 100644 index 0000000..bb1b1bf Binary files /dev/null and b/api/product_library/skg-products/images/skg-vs500-back-and-neck-massager-03.jpg differ diff --git a/api/product_library/skg-products/images/skg-w9-ultra-lower-back-massager-02.jpg b/api/product_library/skg-products/images/skg-w9-ultra-lower-back-massager-02.jpg new file mode 100644 index 0000000..1c873db Binary files /dev/null and b/api/product_library/skg-products/images/skg-w9-ultra-lower-back-massager-02.jpg differ diff --git a/api/product_library/skg-products/images/skg-w9-ultra-lower-back-massager-03.jpg b/api/product_library/skg-products/images/skg-w9-ultra-lower-back-massager-03.jpg new file mode 100644 index 0000000..99cccaa Binary files /dev/null and b/api/product_library/skg-products/images/skg-w9-ultra-lower-back-massager-03.jpg differ diff --git a/api/product_library/skg-products/images/skg-w9-ultra-lower-back-massager-04.jpg b/api/product_library/skg-products/images/skg-w9-ultra-lower-back-massager-04.jpg new file mode 100644 index 0000000..94a07df Binary files /dev/null and b/api/product_library/skg-products/images/skg-w9-ultra-lower-back-massager-04.jpg differ diff --git a/api/product_library/skg-products/images/skg-ys100-foot-massager-12.jpg b/api/product_library/skg-products/images/skg-ys100-foot-massager-12.jpg new file mode 100644 index 0000000..5ad7e8f Binary files /dev/null and b/api/product_library/skg-products/images/skg-ys100-foot-massager-12.jpg differ diff --git a/api/product_library/skg-products/images/skg-ys100-foot-massager-black-2-0-02.jpg b/api/product_library/skg-products/images/skg-ys100-foot-massager-black-2-0-02.jpg new file mode 100644 index 0000000..0be1710 Binary files /dev/null and b/api/product_library/skg-products/images/skg-ys100-foot-massager-black-2-0-02.jpg differ diff --git a/api/product_library/skg-products/images/w9-pro-waist-massager-01.jpg b/api/product_library/skg-products/images/w9-pro-waist-massager-01.jpg new file mode 100644 index 0000000..fb3ee3e Binary files /dev/null and b/api/product_library/skg-products/images/w9-pro-waist-massager-01.jpg differ diff --git a/api/product_library/skg-products/images/w9-pro-waist-massager-04.jpg b/api/product_library/skg-products/images/w9-pro-waist-massager-04.jpg new file mode 100644 index 0000000..fd106ef Binary files /dev/null and b/api/product_library/skg-products/images/w9-pro-waist-massager-04.jpg differ diff --git a/api/product_library/skg-products/images/w9-pro-waist-massager-05.jpg b/api/product_library/skg-products/images/w9-pro-waist-massager-05.jpg new file mode 100644 index 0000000..669acf5 Binary files /dev/null and b/api/product_library/skg-products/images/w9-pro-waist-massager-05.jpg differ diff --git a/api/product_library/skg-products/manifest.json b/api/product_library/skg-products/manifest.json new file mode 100644 index 0000000..dd1fd8d --- /dev/null +++ b/api/product_library/skg-products/manifest.json @@ -0,0 +1,866 @@ +{ + "source": "/Users/kangwan/Desktop/skg/skg_product_downloads", + "filter": "all_products/gallery only; border white_score >= 0.78 or white_score >= 0.62 and near_white_score >= 0.90", + "count": 41, + "items": [ + { + "id": "g7-pro-fold-neck-massager-01", + "handle": "g7-pro-fold-neck-massager", + "title": "SKG G7 PRO-FOLD Foldable Neck Massager with Gentle Warm Function", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 1, + "filename": "images/g7-pro-fold-neck-massager-01.jpg", + "url": "/product-library/skg/images/g7-pro-fold-neck-massager-01.jpg", + "width": 1800, + "height": 1800, + "source_path": "all_products/g7-pro-fold-neck-massager/gallery/01-11-3.jpg", + "white_score": 0.9762, + "near_white_score": 0.9803, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "g7-pro-fold-neck-massager-05", + "handle": "g7-pro-fold-neck-massager", + "title": "SKG G7 PRO-FOLD Foldable Neck Massager with Gentle Warm Function", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 5, + "filename": "images/g7-pro-fold-neck-massager-05.jpg", + "url": "/product-library/skg/images/g7-pro-fold-neck-massager-05.jpg", + "width": 1800, + "height": 1800, + "source_path": "all_products/g7-pro-fold-neck-massager/gallery/05-11-96a45541-70fa-443a-9805-61ccca6b30ca.jpg", + "white_score": 0.9753, + "near_white_score": 0.9794, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "g7-pro-neck-massager-01", + "handle": "g7-pro-neck-massager", + "title": "SKG G7 Pro Smart Neck Massager with Heat", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 1, + "filename": "images/g7-pro-neck-massager-01.jpg", + "url": "/product-library/skg/images/g7-pro-neck-massager-01.jpg", + "width": 1000, + "height": 1000, + "source_path": "all_products/g7-pro-neck-massager/gallery/01-skg-g7-pro-smart-neck-massager-with-heat-651568.jpg", + "white_score": 1.0, + "near_white_score": 1.0, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "g7-pro-neck-massager-02", + "handle": "g7-pro-neck-massager", + "title": "SKG G7 Pro Smart Neck Massager with Heat", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 2, + "filename": "images/g7-pro-neck-massager-02.jpg", + "url": "/product-library/skg/images/g7-pro-neck-massager-02.jpg", + "width": 1800, + "height": 1800, + "source_path": "all_products/g7-pro-neck-massager/gallery/02-skg-g7-pro-smart-neck-massager-with-heat-848777.jpg", + "white_score": 1.0, + "near_white_score": 1.0, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "g7-pro-neck-massager-04", + "handle": "g7-pro-neck-massager", + "title": "SKG G7 Pro Smart Neck Massager with Heat", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 4, + "filename": "images/g7-pro-neck-massager-04.jpg", + "url": "/product-library/skg/images/g7-pro-neck-massager-04.jpg", + "width": 1001, + "height": 1001, + "source_path": "all_products/g7-pro-neck-massager/gallery/04-skg-g7-pro-smart-neck-massager-with-heat-358760.jpg", + "white_score": 0.9137, + "near_white_score": 0.9317, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "g7-pro-neck-massager-07", + "handle": "g7-pro-neck-massager", + "title": "SKG G7 Pro Smart Neck Massager with Heat", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 7, + "filename": "images/g7-pro-neck-massager-07.jpg", + "url": "/product-library/skg/images/g7-pro-neck-massager-07.jpg", + "width": 1001, + "height": 1001, + "source_path": "all_products/g7-pro-neck-massager/gallery/07-e-2022-g7-pro-g7-pro-d94b1b10-f94c-4618-8ec8-9a89ce1830bb.jpg", + "white_score": 0.8281, + "near_white_score": 0.8553, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "g7-pro-neck-massager-11", + "handle": "g7-pro-neck-massager", + "title": "SKG G7 Pro Smart Neck Massager with Heat", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 11, + "filename": "images/g7-pro-neck-massager-11.jpg", + "url": "/product-library/skg/images/g7-pro-neck-massager-11.jpg", + "width": 1001, + "height": 1001, + "source_path": "all_products/g7-pro-neck-massager/gallery/11-cb79b725-a90c-439b-9256-0b8915910168-f093e3a1d3efa18c7ca3196b97a05aa7.jpg", + "white_score": 0.9942, + "near_white_score": 0.9984, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "g7-pro-neck-massager-12", + "handle": "g7-pro-neck-massager", + "title": "SKG G7 Pro Smart Neck Massager with Heat", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 12, + "filename": "images/g7-pro-neck-massager-12.jpg", + "url": "/product-library/skg/images/g7-pro-neck-massager-12.jpg", + "width": 1800, + "height": 1800, + "source_path": "all_products/g7-pro-neck-massager/gallery/12-skg-g7-pro-smart-neck-massager-with-heat-116880.jpg", + "white_score": 1.0, + "near_white_score": 1.0, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "h7-ultra-05", + "handle": "h7-ultra", + "title": "SKG H7 Ultra Neck and Shoulder Massager", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 5, + "filename": "images/h7-ultra-05.jpg", + "url": "/product-library/skg/images/h7-ultra-05.jpg", + "width": 1125, + "height": 1500, + "source_path": "all_products/h7-ultra/gallery/05-61p7odpmgol-ac-sl1500.jpg", + "white_score": 0.9046, + "near_white_score": 0.9507, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "h7-ultra-11", + "handle": "h7-ultra", + "title": "SKG H7 Ultra Neck and Shoulder Massager", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 11, + "filename": "images/h7-ultra-11.jpg", + "url": "/product-library/skg/images/h7-ultra-11.jpg", + "width": 1125, + "height": 1500, + "source_path": "all_products/h7-ultra/gallery/11-71py-ebgmjl-ac-sl1500.jpg", + "white_score": 0.8133, + "near_white_score": 0.8701, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "k5-pro-neck-massager-02", + "handle": "k5-pro-neck-massager", + "title": "SKG K5-3 Pro Intelligent Neck Massager with Heat", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 2, + "filename": "images/k5-pro-neck-massager-02.jpg", + "url": "/product-library/skg/images/k5-pro-neck-massager-02.jpg", + "width": 1000, + "height": 1000, + "source_path": "all_products/k5-pro-neck-massager/gallery/02-skg-k5-pro-intelligent-neck-massager-with-heat-452498.jpg", + "white_score": 1.0, + "near_white_score": 1.0, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "skg-flex-massager-h7-ultra-e-01", + "handle": "skg-flex-massager-h7-ultra-e", + "title": "SKG H7 Ultra E Neck and Shoulder Flex Massager", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 1, + "filename": "images/skg-flex-massager-h7-ultra-e-01.jpg", + "url": "/product-library/skg/images/skg-flex-massager-h7-ultra-e-01.jpg", + "width": 1800, + "height": 1800, + "source_path": "all_products/skg-flex-massager-h7-ultra-e/gallery/01-image-1-536314fe-3ebc-414d-a03c-6e32d077f608.jpg", + "white_score": 0.8289, + "near_white_score": 0.838, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "skg-flex-massager-h7-ultra-e-06", + "handle": "skg-flex-massager-h7-ultra-e", + "title": "SKG H7 Ultra E Neck and Shoulder Flex Massager", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 6, + "filename": "images/skg-flex-massager-h7-ultra-e-06.jpg", + "url": "/product-library/skg/images/skg-flex-massager-h7-ultra-e-06.jpg", + "width": 1800, + "height": 1800, + "source_path": "all_products/skg-flex-massager-h7-ultra-e/gallery/06-20250320-101625.jpg", + "white_score": 0.7952, + "near_white_score": 0.8553, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "skg-g7-pro-fold-golden-neck-massager-02", + "handle": "skg-g7-pro-fold-golden-neck-massager", + "title": "SKG G7 Pro Fold-Golden Neck Massager", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 2, + "filename": "images/skg-g7-pro-fold-golden-neck-massager-02.jpg", + "url": "/product-library/skg/images/skg-g7-pro-fold-golden-neck-massager-02.jpg", + "width": 1800, + "height": 1800, + "source_path": "all_products/skg-g7-pro-fold-golden-neck-massager/gallery/02-2-98b3fae1-5c0e-47d0-8b9a-c5153ff83c3a.png", + "white_score": 0.9836, + "near_white_score": 0.9885, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "skg-g7-pro-fold-golden-neck-massager-03", + "handle": "skg-g7-pro-fold-golden-neck-massager", + "title": "SKG G7 Pro Fold-Golden Neck Massager", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 3, + "filename": "images/skg-g7-pro-fold-golden-neck-massager-03.jpg", + "url": "/product-library/skg/images/skg-g7-pro-fold-golden-neck-massager-03.jpg", + "width": 1800, + "height": 1800, + "source_path": "all_products/skg-g7-pro-fold-golden-neck-massager/gallery/03-1-35d3f741-a3a5-4893-b076-f86b4cad8edc.png", + "white_score": 0.8898, + "near_white_score": 0.9005, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "skg-h5-mini-cordless-shiatsu-neck-and-shoulder-massager-with-heat-01", + "handle": "skg-h5-mini-cordless-shiatsu-neck-and-shoulder-massager-with-heat", + "title": "SKG H5 Mini Cordless Shiatsu Neck and Shoulder Massager with Heat", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 1, + "filename": "images/skg-h5-mini-cordless-shiatsu-neck-and-shoulder-massager-with-heat-01.jpg", + "url": "/product-library/skg/images/skg-h5-mini-cordless-shiatsu-neck-and-shoulder-massager-with-heat-01.jpg", + "width": 1800, + "height": 1800, + "source_path": "all_products/skg-h5-mini-cordless-shiatsu-neck-and-shoulder-massager-with-heat/gallery/01-1-8e35c077-3381-444f-9daa-b88610f6402d.jpg", + "white_score": 0.9013, + "near_white_score": 0.9112, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "skg-h5-mini-cordless-shiatsu-neck-and-shoulder-massager-with-heat-08", + "handle": "skg-h5-mini-cordless-shiatsu-neck-and-shoulder-massager-with-heat", + "title": "SKG H5 Mini Cordless Shiatsu Neck and Shoulder Massager with Heat", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 8, + "filename": "images/skg-h5-mini-cordless-shiatsu-neck-and-shoulder-massager-with-heat-08.jpg", + "url": "/product-library/skg/images/skg-h5-mini-cordless-shiatsu-neck-and-shoulder-massager-with-heat-08.jpg", + "width": 1350, + "height": 1800, + "source_path": "all_products/skg-h5-mini-cordless-shiatsu-neck-and-shoulder-massager-with-heat/gallery/08-6-97e250be-47a6-494b-a4aa-58fb5bd9411e.jpg", + "white_score": 0.6735, + "near_white_score": 0.9942, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "skg-h5-mini-cordless-shiatsu-neck-and-shoulder-massager-with-heat-09", + "handle": "skg-h5-mini-cordless-shiatsu-neck-and-shoulder-massager-with-heat", + "title": "SKG H5 Mini Cordless Shiatsu Neck and Shoulder Massager with Heat", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 9, + "filename": "images/skg-h5-mini-cordless-shiatsu-neck-and-shoulder-massager-with-heat-09.jpg", + "url": "/product-library/skg/images/skg-h5-mini-cordless-shiatsu-neck-and-shoulder-massager-with-heat-09.jpg", + "width": 1350, + "height": 1800, + "source_path": "all_products/skg-h5-mini-cordless-shiatsu-neck-and-shoulder-massager-with-heat/gallery/09-7-a1c3f484-43ec-4622-9667-2ace292c3d6a.jpg", + "white_score": 0.7911, + "near_white_score": 0.8684, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "skg-knee-massager-ws500-01", + "handle": "skg-knee-massager-ws500", + "title": "SKG WS500 Knee Massager", + "product_type": "Knee Massager", + "image_type": "gallery", + "image_index": 1, + "filename": "images/skg-knee-massager-ws500-01.jpg", + "url": "/product-library/skg/images/skg-knee-massager-ws500-01.jpg", + "width": 500, + "height": 500, + "source_path": "all_products/skg-knee-massager-ws500/gallery/01-2-3343c351-0c0b-47d8-b8c6-3037e2871335.jpg", + "white_score": 0.9589, + "near_white_score": 0.9663, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Knee Massager" + ] + }, + { + "id": "skg-knee-massager-ws500-03", + "handle": "skg-knee-massager-ws500", + "title": "SKG WS500 Knee Massager", + "product_type": "Knee Massager", + "image_type": "gallery", + "image_index": 3, + "filename": "images/skg-knee-massager-ws500-03.jpg", + "url": "/product-library/skg/images/skg-knee-massager-ws500-03.jpg", + "width": 500, + "height": 500, + "source_path": "all_products/skg-knee-massager-ws500/gallery/03-4-ff0fbc01-a3ae-4c61-82ba-005c161151b9.jpg", + "white_score": 0.9753, + "near_white_score": 0.9794, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Knee Massager" + ] + }, + { + "id": "skg-knee-massager-ws500-04", + "handle": "skg-knee-massager-ws500", + "title": "SKG WS500 Knee Massager", + "product_type": "Knee Massager", + "image_type": "gallery", + "image_index": 4, + "filename": "images/skg-knee-massager-ws500-04.jpg", + "url": "/product-library/skg/images/skg-knee-massager-ws500-04.jpg", + "width": 500, + "height": 500, + "source_path": "all_products/skg-knee-massager-ws500/gallery/04-3-570f8251-7f7e-45e0-be04-81b6aceff8a5.jpg", + "white_score": 0.9605, + "near_white_score": 0.9696, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Knee Massager" + ] + }, + { + "id": "skg-knee-massager-ws500-05", + "handle": "skg-knee-massager-ws500", + "title": "SKG WS500 Knee Massager", + "product_type": "Knee Massager", + "image_type": "gallery", + "image_index": 5, + "filename": "images/skg-knee-massager-ws500-05.jpg", + "url": "/product-library/skg/images/skg-knee-massager-ws500-05.jpg", + "width": 500, + "height": 500, + "source_path": "all_products/skg-knee-massager-ws500/gallery/05-6-452f832b-ea1d-4137-ba79-b99cebb93634.jpg", + "white_score": 0.9975, + "near_white_score": 0.9992, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Knee Massager" + ] + }, + { + "id": "skg-neck-and-shoulder-massager-hs500-2-01", + "handle": "skg-neck-and-shoulder-massager-hs500-2", + "title": "SKG HS500-2 Neck and Shoulder Massager", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 1, + "filename": "images/skg-neck-and-shoulder-massager-hs500-2-01.jpg", + "url": "/product-library/skg/images/skg-neck-and-shoulder-massager-hs500-2-01.jpg", + "width": 1800, + "height": 1800, + "source_path": "all_products/skg-neck-and-shoulder-massager-hs500-2/gallery/01-1-2-c80c3785-9064-4506-b8c2-0ad1d8217cb4.jpg", + "white_score": 0.889, + "near_white_score": 0.9013, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "skg-neck-and-shoulder-massager-hs500-2-06", + "handle": "skg-neck-and-shoulder-massager-hs500-2", + "title": "SKG HS500-2 Neck and Shoulder Massager", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 6, + "filename": "images/skg-neck-and-shoulder-massager-hs500-2-06.jpg", + "url": "/product-library/skg/images/skg-neck-and-shoulder-massager-hs500-2-06.jpg", + "width": 1800, + "height": 1800, + "source_path": "all_products/skg-neck-and-shoulder-massager-hs500-2/gallery/06-6-35028d3f-bea8-4929-a1e5-dafdd88dba05.jpg", + "white_score": 0.8413, + "near_white_score": 0.9416, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "skg-neck-and-shoulder-massager-hs500-2-10", + "handle": "skg-neck-and-shoulder-massager-hs500-2", + "title": "SKG HS500-2 Neck and Shoulder Massager", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 10, + "filename": "images/skg-neck-and-shoulder-massager-hs500-2-10.jpg", + "url": "/product-library/skg/images/skg-neck-and-shoulder-massager-hs500-2-10.jpg", + "width": 1800, + "height": 1800, + "source_path": "all_products/skg-neck-and-shoulder-massager-hs500-2/gallery/10-3-f1a09094-f423-427d-bb66-91dbd14b3702.jpg", + "white_score": 0.9786, + "near_white_score": 0.9868, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "skg-neck-and-shoulder-massager-hs500-2-11", + "handle": "skg-neck-and-shoulder-massager-hs500-2", + "title": "SKG HS500-2 Neck and Shoulder Massager", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 11, + "filename": "images/skg-neck-and-shoulder-massager-hs500-2-11.jpg", + "url": "/product-library/skg/images/skg-neck-and-shoulder-massager-hs500-2-11.jpg", + "width": 1800, + "height": 1800, + "source_path": "all_products/skg-neck-and-shoulder-massager-hs500-2/gallery/11-2-d0dac807-5777-4001-a7fd-1aa92742d17b.jpg", + "white_score": 0.9021, + "near_white_score": 0.9095, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "skg-neck-and-shoulder-massager-hs500-2-12", + "handle": "skg-neck-and-shoulder-massager-hs500-2", + "title": "SKG HS500-2 Neck and Shoulder Massager", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 12, + "filename": "images/skg-neck-and-shoulder-massager-hs500-2-12.jpg", + "url": "/product-library/skg/images/skg-neck-and-shoulder-massager-hs500-2-12.jpg", + "width": 1800, + "height": 1800, + "source_path": "all_products/skg-neck-and-shoulder-massager-hs500-2/gallery/12-5-6454717b-4570-48d5-9596-378a278cb763.jpg", + "white_score": 0.9803, + "near_white_score": 0.986, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "skg-neck-massager-gs500-n-01", + "handle": "skg-neck-massager-gs500-n", + "title": "SKG GS500-N Neck Massager", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 1, + "filename": "images/skg-neck-massager-gs500-n-01.jpg", + "url": "/product-library/skg/images/skg-neck-massager-gs500-n-01.jpg", + "width": 1800, + "height": 1800, + "source_path": "all_products/skg-neck-massager-gs500-n/gallery/01-1-e5f77c48-51d9-450a-84e9-7e6502df1f8d.jpg", + "white_score": 1.0, + "near_white_score": 1.0, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "skg-neck-massager-gs500-n-03", + "handle": "skg-neck-massager-gs500-n", + "title": "SKG GS500-N Neck Massager", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 3, + "filename": "images/skg-neck-massager-gs500-n-03.jpg", + "url": "/product-library/skg/images/skg-neck-massager-gs500-n-03.jpg", + "width": 1800, + "height": 1800, + "source_path": "all_products/skg-neck-massager-gs500-n/gallery/03-2-f27e8b0f-023d-43a2-b934-ed7a13cb54f6.jpg", + "white_score": 0.9942, + "near_white_score": 0.9975, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "skg-neck-massager-gs500-n-04", + "handle": "skg-neck-massager-gs500-n", + "title": "SKG GS500-N Neck Massager", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 4, + "filename": "images/skg-neck-massager-gs500-n-04.jpg", + "url": "/product-library/skg/images/skg-neck-massager-gs500-n-04.jpg", + "width": 1800, + "height": 1800, + "source_path": "all_products/skg-neck-massager-gs500-n/gallery/04-4-fe265164-3b78-4f45-b1b9-53c47f0db027.jpg", + "white_score": 0.9975, + "near_white_score": 0.9984, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "skg-neck-massager-gs500-n-05", + "handle": "skg-neck-massager-gs500-n", + "title": "SKG GS500-N Neck Massager", + "product_type": "Neck Massager", + "image_type": "gallery", + "image_index": 5, + "filename": "images/skg-neck-massager-gs500-n-05.jpg", + "url": "/product-library/skg/images/skg-neck-massager-gs500-n-05.jpg", + "width": 1800, + "height": 1800, + "source_path": "all_products/skg-neck-massager-gs500-n/gallery/05-5-d8c18f90-7376-431d-aa53-a24599db08b3.jpg", + "white_score": 0.9762, + "near_white_score": 0.9877, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Neck Massager" + ] + }, + { + "id": "skg-vs500-back-and-neck-massager-01", + "handle": "skg-vs500-back-and-neck-massager", + "title": "SKG VS500 Back Massage Pillow", + "product_type": "Waist Massager", + "image_type": "gallery", + "image_index": 1, + "filename": "images/skg-vs500-back-and-neck-massager-01.jpg", + "url": "/product-library/skg/images/skg-vs500-back-and-neck-massager-01.jpg", + "width": 1800, + "height": 1800, + "source_path": "all_products/skg-vs500-back-and-neck-massager/gallery/01-120.png", + "white_score": 1.0, + "near_white_score": 1.0, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Waist Massager" + ] + }, + { + "id": "skg-vs500-back-and-neck-massager-03", + "handle": "skg-vs500-back-and-neck-massager", + "title": "SKG VS500 Back Massage Pillow", + "product_type": "Waist Massager", + "image_type": "gallery", + "image_index": 3, + "filename": "images/skg-vs500-back-and-neck-massager-03.jpg", + "url": "/product-library/skg/images/skg-vs500-back-and-neck-massager-03.jpg", + "width": 1800, + "height": 1800, + "source_path": "all_products/skg-vs500-back-and-neck-massager/gallery/03-3-1.png", + "white_score": 1.0, + "near_white_score": 1.0, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Waist Massager" + ] + }, + { + "id": "skg-w9-ultra-lower-back-massager-02", + "handle": "skg-w9-ultra-lower-back-massager", + "title": "SKG W9 Ultra Lower Back Massager", + "product_type": "WAIST MASSAGER", + "image_type": "gallery", + "image_index": 2, + "filename": "images/skg-w9-ultra-lower-back-massager-02.jpg", + "url": "/product-library/skg/images/skg-w9-ultra-lower-back-massager-02.jpg", + "width": 1800, + "height": 1800, + "source_path": "all_products/skg-w9-ultra-lower-back-massager/gallery/02-177250074092.png", + "white_score": 0.9597, + "near_white_score": 0.9605, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "WAIST MASSAGER" + ] + }, + { + "id": "skg-w9-ultra-lower-back-massager-03", + "handle": "skg-w9-ultra-lower-back-massager", + "title": "SKG W9 Ultra Lower Back Massager", + "product_type": "WAIST MASSAGER", + "image_type": "gallery", + "image_index": 3, + "filename": "images/skg-w9-ultra-lower-back-massager-03.jpg", + "url": "/product-library/skg/images/skg-w9-ultra-lower-back-massager-03.jpg", + "width": 1800, + "height": 1800, + "source_path": "all_products/skg-w9-ultra-lower-back-massager/gallery/03-1772500736668.png", + "white_score": 0.9803, + "near_white_score": 0.9803, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "WAIST MASSAGER" + ] + }, + { + "id": "skg-w9-ultra-lower-back-massager-04", + "handle": "skg-w9-ultra-lower-back-massager", + "title": "SKG W9 Ultra Lower Back Massager", + "product_type": "WAIST MASSAGER", + "image_type": "gallery", + "image_index": 4, + "filename": "images/skg-w9-ultra-lower-back-massager-04.jpg", + "url": "/product-library/skg/images/skg-w9-ultra-lower-back-massager-04.jpg", + "width": 1800, + "height": 1800, + "source_path": "all_products/skg-w9-ultra-lower-back-massager/gallery/04-17725007288637.png", + "white_score": 0.9712, + "near_white_score": 0.9819, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "WAIST MASSAGER" + ] + }, + { + "id": "skg-ys100-foot-massager-12", + "handle": "skg-ys100-foot-massager", + "title": "SKG YS100 Foot Massager", + "product_type": "", + "image_type": "gallery", + "image_index": 12, + "filename": "images/skg-ys100-foot-massager-12.jpg", + "url": "/product-library/skg/images/skg-ys100-foot-massager-12.jpg", + "width": 1600, + "height": 1154, + "source_path": "all_products/skg-ys100-foot-massager/gallery/12-2-a9933337-b122-4cfb-a4fa-1dc82a5d763d.png", + "white_score": 0.7862, + "near_white_score": 0.8133, + "has_people": false, + "tags": [ + "white-bg", + "gallery" + ] + }, + { + "id": "skg-ys100-foot-massager-black-2-0-02", + "handle": "skg-ys100-foot-massager-black-2-0", + "title": "SKG YS100 Foot Massager Black 2.0", + "product_type": "", + "image_type": "gallery", + "image_index": 2, + "filename": "images/skg-ys100-foot-massager-black-2-0-02.jpg", + "url": "/product-library/skg/images/skg-ys100-foot-massager-black-2-0-02.jpg", + "width": 1502, + "height": 1502, + "source_path": "all_products/skg-ys100-foot-massager-black-2-0/gallery/02-1-1-48e79179-3270-45d9-9903-e46c03c97e65.jpg", + "white_score": 0.8742, + "near_white_score": 0.8775, + "has_people": false, + "tags": [ + "white-bg", + "gallery" + ] + }, + { + "id": "w9-pro-waist-massager-01", + "handle": "w9-pro-waist-massager", + "title": "SKG W9 Pro Lower Back Massager", + "product_type": "Waist Massager", + "image_type": "gallery", + "image_index": 1, + "filename": "images/w9-pro-waist-massager-01.jpg", + "url": "/product-library/skg/images/w9-pro-waist-massager-01.jpg", + "width": 1800, + "height": 1800, + "source_path": "all_products/w9-pro-waist-massager/gallery/01-2-a06084ba-9c70-4f10-82b7-9612f818c61a.jpg", + "white_score": 0.9696, + "near_white_score": 0.9753, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Waist Massager" + ] + }, + { + "id": "w9-pro-waist-massager-04", + "handle": "w9-pro-waist-massager", + "title": "SKG W9 Pro Lower Back Massager", + "product_type": "Waist Massager", + "image_type": "gallery", + "image_index": 4, + "filename": "images/w9-pro-waist-massager-04.jpg", + "url": "/product-library/skg/images/w9-pro-waist-massager-04.jpg", + "width": 1350, + "height": 1800, + "source_path": "all_products/w9-pro-waist-massager/gallery/04-1-47db56ea-162a-44fc-a9cf-6d44c79930b2.jpg", + "white_score": 0.866, + "near_white_score": 0.875, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Waist Massager" + ] + }, + { + "id": "w9-pro-waist-massager-05", + "handle": "w9-pro-waist-massager", + "title": "SKG W9 Pro Lower Back Massager", + "product_type": "Waist Massager", + "image_type": "gallery", + "image_index": 5, + "filename": "images/w9-pro-waist-massager-05.jpg", + "url": "/product-library/skg/images/w9-pro-waist-massager-05.jpg", + "width": 1350, + "height": 1800, + "source_path": "all_products/w9-pro-waist-massager/gallery/05-2-daa222c5-f098-48cd-a50b-baac4a8c2f31.jpg", + "white_score": 0.9375, + "near_white_score": 0.9688, + "has_people": false, + "tags": [ + "white-bg", + "gallery", + "Waist Massager" + ] + } + ] +} \ No newline at end of file diff --git a/web/lib/api.ts b/web/lib/api.ts index f8ba96a..b4e9857 100644 --- a/web/lib/api.ts +++ b/web/lib/api.ts @@ -118,6 +118,28 @@ export async function uploadStoryboardAsset(jobId: string, file: File): Promise< return res.json() } +export async function listProductLibrary(): Promise { + const res = await fetch(`${API_BASE}/product-library/skg`) + if (!res.ok) { + const txt = await res.text().catch(() => "") + throw new Error(`listProductLibrary ${res.status} ${txt.slice(0, 300)}`) + } + return res.json() +} + +export async function copyProductLibraryAsset(jobId: string, productId: string): Promise { + const res = await fetch(`${API_BASE}/jobs/${jobId}/assets/product-library`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ product_id: productId }), + }) + if (!res.ok) { + const txt = await res.text().catch(() => "") + throw new Error(`copyProductLibraryAsset ${res.status} ${txt.slice(0, 300)}`) + } + return res.json() +} + export interface KeyFrame { index: number timestamp: number @@ -180,6 +202,24 @@ export interface SubjectAsset { created_at: number } +export interface ProductLibraryItem { + id: string + handle: string + title: string + product_type: string + image_type: string + image_index: number + filename: string + url: string + width: number + height: number + source_path: string + white_score: number + near_white_score: number + has_people: boolean + tags: string[] +} + export interface TranscriptSegment { index: number start: number