Video QC: add platform-zones lookup helper for title_safe

Adds _PLATFORM_ZONES (TikTok / IG Stories / IG Reels / generic vertical)
and _infer_platform_zones(filename) for use by the new title_safe check.
Pure function, verified at REPL against expected filenames. No new
behaviour exposed yet — wired up in the next task.
This commit is contained in:
nickviljoen 2026-05-15 12:05:25 +02:00
parent 78f61e0ba2
commit 4ada4c2d59

View file

@ -44,6 +44,83 @@ def _language_display(lang_code: str) -> str:
return _LANG_NAMES.get(lang_code.lower(), f"language code '{lang_code}'")
# Platform UI overlay zones for `title_safe` check. Each entry describes the
# regions of the frame that the platform's UI obscures (profile pills, captions,
# action icons). Used to flag when price or garment-name text lands inside.
# Percentages are conservative — tuned against IG/TikTok screenshots circa 2026.
_PLATFORM_ZONES = {
'tiktok': {
'description': "TikTok feed: top ~10% (profile/handle bar), bottom ~25% "
"(caption + UI action rail).",
'zones': [
{'edge': 'top', 'percent': 10},
{'edge': 'bottom', 'percent': 25},
],
},
'ig_stories': {
'description': "Instagram Stories: top ~12% (profile pill + reactions), "
"bottom ~18% (swipe-up / reply bar).",
'zones': [
{'edge': 'top', 'percent': 12},
{'edge': 'bottom', 'percent': 18},
],
},
'ig_reels': {
'description': "Instagram Reels: bottom ~25% (caption + icons), "
"right edge ~10% (action rail).",
'zones': [
{'edge': 'bottom', 'percent': 25},
{'edge': 'right', 'percent': 10},
],
},
'vertical_generic': {
'description': "Generic vertical (9x16) social: top ~10%, bottom ~20%.",
'zones': [
{'edge': 'top', 'percent': 10},
{'edge': 'bottom', 'percent': 20},
],
},
}
def _infer_platform_zones(filename: str) -> dict | None:
"""Infer platform UI overlay zones from filename tokens.
Returns a dict {'platform': str, 'description': str, 'zones': [...]}
or None when the format has no known overlay zones (feed formats like
1x1 / 4x5, or unrecognised).
The returned dict is freshly built (deep-copied zones list) so callers
can mutate it without corrupting the module-level _PLATFORM_ZONES.
"""
if not filename:
return None
upper = filename.upper()
def _build(key: str) -> dict:
base = _PLATFORM_ZONES[key]
return {
'platform': key,
'description': base['description'],
'zones': [dict(z) for z in base['zones']],
}
# Most specific first: explicit platform + format combos.
if 'TK_STORIES' in upper or '_TK_' in upper or 'TT_9X16' in upper:
return _build('tiktok')
if 'IG_STORIES' in upper or 'STORIES_9X16' in upper:
return _build('ig_stories')
if 'IG_REELS' in upper or 'REELS_9X16' in upper:
return _build('ig_reels')
# Fallback: any 9x16 with no platform hint -> generic vertical.
if '9X16' in upper:
return _build('vertical_generic')
# Feed formats (1x1, 4x5) and anything else -> no overlay zones.
return None
class VideoQCExecutor:
"""Execute video QC checks with frame extraction and AI analysis."""