Skip to content

Commit 9ecb7b3

Browse files
fix(mixkit): don't guess JSON-LD clip dimensions from the filename
The JSON-LD fallback reported every "-1080" contentUrl as 1920x1080 and everything else as 1280x720, so portrait clips surfaced as landscape. Use the VideoObject's declared width/height (number, string, or QuantitativeValue) and leave them 0 (unknown) when absent, matching the card path. Adds portrait and missing-dimension JSON-LD tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 25800e2 commit 9ecb7b3

2 files changed

Lines changed: 43 additions & 7 deletions

File tree

‎tests/tools/test_stock_source_adapters.py‎

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ def fake_get(url, headers=None, params=None, timeout=None):
251251
assert (results[0].width, results[0].height) == (1920, 1080)
252252

253253

254-
def test_mixkit_falls_back_to_json_ld_video_objects(monkeypatch):
254+
def _mixkit_json_ld_search(monkeypatch, extra_fields=""):
255255
# Mixkit's current markup has no result cards, only schema.org JSON-LD.
256256
pytest.importorskip("bs4")
257257
html = """<html><head><script type="application/ld+json">
@@ -263,18 +263,39 @@ def test_mixkit_falls_back_to_json_ld_video_objects(monkeypatch):
263263
"description": "Round candle lit illuminating while it goes out.",
264264
"thumbnailUrl": "https://assets.mixkit.co/videos/3458/3458-thumb-720-0.jpg",
265265
"contentUrl": "https://assets.mixkit.co/videos/3458/3458-1080.mp4",
266+
%s
266267
"embedUrl": "https://assets.mixkit.co/videos/3458/3458-360.mp4"}
267-
]}</script></head><body></body></html>"""
268+
]}</script></head><body></body></html>""" % extra_fields
268269
requests_stub = types.ModuleType("requests")
269270
requests_stub.get = lambda *_a, **_k: _JsonResponse(text=html)
270271
monkeypatch.setitem(sys.modules, "requests", requests_stub)
272+
return get_source("mixkit").search("candle", SearchFilters(kind="video", per_page=5))
273+
271274

272-
results = get_source("mixkit").search("candle", SearchFilters(kind="video", per_page=5))
275+
def test_mixkit_falls_back_to_json_ld_video_objects(monkeypatch):
276+
results = _mixkit_json_ld_search(monkeypatch)
273277

274278
assert len(results) == 1
275279
clip = results[0]
276280
assert clip.source_id == "mixkit_3458"
277281
assert clip.download_url == "https://assets.mixkit.co/videos/3458/3458-1080.mp4"
278282
assert clip.extra["detail_url"] == clip.download_url
279-
assert (clip.width, clip.height) == (1920, 1080)
280283
assert "Candle lighting in the dark" in clip.source_tags
284+
# No declared size: stay unknown rather than guessing from the "-1080" suffix.
285+
assert (clip.width, clip.height) == (0, 0)
286+
287+
288+
@pytest.mark.parametrize(
289+
"fields",
290+
[
291+
'"width": 1080, "height": 1920,',
292+
'"width": "1080", "height": "1920 px",',
293+
'"width": {"@type": "QuantitativeValue", "value": 1080},'
294+
' "height": {"@type": "QuantitativeValue", "value": 1920},',
295+
],
296+
ids=["numbers", "strings", "quantitative-value"],
297+
)
298+
def test_mixkit_json_ld_keeps_declared_portrait_dimensions(monkeypatch, fields):
299+
(clip,) = _mixkit_json_ld_search(monkeypatch, fields)
300+
301+
assert (clip.width, clip.height) == (1080, 1920)

‎tools/video/stock_sources/mixkit.py‎

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,20 @@
2929
_LICENSE = "Mixkit License (free for commercial and personal use, no attribution required)"
3030

3131

32+
def _ld_dimension(value: Any) -> int:
33+
"""Pixel size from a schema.org width/height (number, "1920", "1920 px",
34+
or a QuantitativeValue). Returns 0 when absent or unparseable."""
35+
if isinstance(value, dict):
36+
value = value.get("value")
37+
if isinstance(value, (int, float)):
38+
return max(0, int(value))
39+
if isinstance(value, str):
40+
match = re.match(r"\s*(\d+)", value)
41+
if match:
42+
return int(match.group(1))
43+
return 0
44+
45+
3246
class MixkitSource:
3347
"""Mixkit video adapter. Satisfies `StockSource`."""
3448

@@ -164,16 +178,17 @@ def _parse_json_ld(self, soup, query: str, filters: SearchFilters) -> list[Candi
164178
continue
165179
href = (node.get("@id") or "").split("#", 1)[0]
166180
clip_id = href.rstrip("/").rsplit("-", 1)[-1] if href else content_url
167-
hd = "-1080." in content_url
168181
out.append(
169182
Candidate(
170183
source=self.name,
171184
source_id=f"mixkit_{clip_id}",
172185
source_url=href or content_url,
173186
download_url=content_url,
174187
kind="video",
175-
width=1920 if hd else 1280,
176-
height=1080 if hd else 720,
188+
# Only trust declared dimensions; the "-1080" filename suffix
189+
# says nothing about orientation. 0 = unknown until probed.
190+
width=_ld_dimension(node.get("width")),
191+
height=_ld_dimension(node.get("height")),
177192
duration=0.0,
178193
creator="Mixkit",
179194
license=_LICENSE,

0 commit comments

Comments
 (0)