VideoObject for a product video: thumbnail, date and duration
Google's VideoObject needs name, thumbnailUrl and uploadDate. How to fill them and the duration from a Sume trim result and a video-frames still.
To mark up a product video for Google, put a VideoObject on the page where people watch it, with three required properties: name, thumbnailUrl and uploadDate. Add contentUrl (the video file itself), description and duration as recommended ones. A Sume trim result gives you duration_seconds for the duration, and a video-frames still gives you a thumbnail image; you host both on your own domain.
Which VideoObject properties does Google require?
Google's page splits them into required and recommended. Missing a required one means Google may not extract any information about the video.
| Property | Status | What Google says |
|---|---|---|
name | Required | Title of the video; unique for each video on your site |
thumbnailUrl | Required | URL of the video's unique thumbnail image file |
uploadDate | Required | When the video was first published, ISO 8601; include a time zone |
contentUrl | Recommended | URL of the video file's actual content bytes, not the page it lives on |
embedUrl | Recommended | A player URL, an alternative when contentUrl is not available |
duration | Recommended | ISO 8601, for example PT00H30M5S |
description | Recommended | Unique per video; HTML tags are ignored |
What must be true of the thumbnail?
Google's best-practices page asks for a valid thumbnail at a stable URL. It lists BMP, GIF, JPEG, PNG, WebP, SVG and AVIF, a minimum size of 60x30 pixels with larger preferred, and says Googlebot must be able to fetch it (no robots.txt block or login). It warns that CDNs with quickly expiring URLs can stop the video from being indexed.
That last point decides where the files live. Video frames returns durable image artifacts on media.sume.com, but a thumbnail you reference from a product page is part of your site. Copy the still to your own store or CDN and use that URL, so you control it for as long as the page exists.
How do you get the still and the duration from Sume?
For the still, call POST /v1/video-frames with the clip's media.sume.com URL and at: [1.5]. It returns 202; read GET /v1/video-frames/:id until resource_status is ready, then take frames[0].url. For the duration, a video trim result carries duration_seconds of the new MP4, and the video-frames result carries source_duration_seconds.
The script below turns those two values into the JSON-LD block. It uses placeholders for your own hosted URLs; replace them before publishing.
import json
def iso_duration(seconds):
minutes, secs = divmod(round(seconds), 60)
return f"PT{minutes}M{secs}S" if minutes else f"PT{secs}S"
trim_result = {"duration_seconds": 12.0}
page_video = {
"name": "Ceramic mug: 12 second product turn",
"thumb": "https://shop.example.com/cdn/mug-poster.jpg",
"file": "https://shop.example.com/cdn/mug-turn.mp4",
}
video_object = {
"@context": "https://schema.org/",
"@type": "VideoObject",
"name": page_video["name"],
"description": "A 12 second turn of the mug on a desk.",
"thumbnailUrl": [page_video["thumb"]],
"uploadDate": "2026-10-03T08:00:00+09:00",
"duration": iso_duration(trim_result["duration_seconds"]),
"contentUrl": page_video["file"],
}
print(json.dumps(video_object, indent=2))Does a short product clip qualify for key moments?
Plain VideoObject has no minimum length on the page I read. The extra features do. For Clip and SeekToAction markup, Google says the video must be able to deep link to a point other than the start and the total duration must be at least 30 seconds. A 12-second product turn is fine for basic markup but not for key moments.
Last, put the markup on the page where the video actually plays. In its Clip and SeekToAction guidelines Google says VideoObject structured data must be added to a page where users can watch the video, and the same rule is sensible for any markup. Test the page with Google's own tools after you publish, since this post cannot tell you whether a rich result will show.
Sources
Related posts
More in Developers
- Virtual try-on API: which Sume call returns an image, which a video
Need a try-on photo or a try-on clip? On Sume the two catalog try-on Formats return video; a still comes from the image API. The table, plus one call for each.
- Unit-test a Sume submit-and-poll loop in Vitest with fake replies
Test a Sume polling loop without spending credits: inject the sleep, replay queued then completed replies, and assert next_poll_after_seconds is honored.
- VS Code chat.mcp.autostart newAndOutdated: Sume's first run
VS Code can start MCP servers automatically when their config changes. Learn the autostart modes and the trust dialog before you add Sume's hosted server.
- waitForRun timeout: why SumeRunTimeoutError can arrive early
The Sume SDK's waitForRun checks its deadline before it sleeps, so SumeRunTimeoutError can fire up to one poll interval early. The run keeps going.
Written by Sume