Draft 1.0, proposed
Quick start: L1 in five minutes
Level L1 means crawlers and agents can read your video moments. A static site gets there with five plain files and no server code. Replace example.com and the example video with your own.
What you need: a site you can add files to, one video page, and one moment on that video (a start and end time in milliseconds).
What you get: a manifest, a catalog, JSON-LD Clips, llms.txt and an RSL license: every L1 surface in spec section 5.1.
1. Write /arv.json #
The catalog lists your videos (assets) and the moments on them. Name each moment by its range, arv:{asset_id}#t={start_ms},{end_ms}, and give it a deep link that opens the video at the start.
{
"arv": "1.0",
"origin": "https://example.com",
"publisher": {
"name": "Example Garage"
},
"assets": [
{
"arv": "1.0",
"id": "vid_8f2c",
"title": "Tuning a carburettor",
"duration_ms": 1284000,
"language": "en",
"content_hash": "sha256:9b1e...",
"creator": {
"id": "cr_12",
"name": "Example Garage",
"url": "https://example.com"
},
"page_url": "https://example.com/videos/carb",
"c2pa": {
"credentials_url": "https://example.com/c2pa/vid_8f2c"
},
"extensions": {
"com.mux": {
"playback_id": "abc"
}
}
}
],
"moments": [
{
"arv": "1.0",
"id": "mom_rg2e4kdenkmkzilboihacumshn",
"moment_uri": "arv:vid_8f2c#t=12400,31000",
"moment_url": "https://example.com/videos/carb#t=12.4,31",
"asset_id": "vid_8f2c",
"start_ms": 12400,
"end_ms": 31000,
"snap": "sentence",
"title": "Setting the idle mixture screw",
"evidence": [
{
"type": "transcript",
"start_ms": 12900,
"end_ms": 18200,
"text": "Turn the mixture screw a quarter turn out",
"confidence": 0.93
},
{
"type": "shot_caption",
"start_ms": 14000,
"end_ms": 22000,
"text": "Close-up of a screwdriver on the idle screw",
"confidence": 0.81
}
],
"evidence_grade": "C",
"confidence": {
"score": 0.84,
"band": "high"
},
"aliases": [
"amt_2b7c..."
]
}
]
}The moment id is not random. It is mom_ plus the first 26 characters of the lowercase base32 SHA-256 of {origin}|{asset_id}|{start_ms}|{end_ms}, so anyone can check it. Compute yours:
import { createHash } from "node:crypto";
const momentId = (origin, assetId, startMs, endMs) => {
const hash = createHash("sha256").update(`${origin}|${assetId}|${startMs}|${endMs}`).digest();
const abc = "abcdefghijklmnopqrstuvwxyz234567";
let bits = "", out = "";
for (const byte of hash) bits += byte.toString(2).padStart(8, "0");
for (let i = 0; i + 5 <= bits.length; i += 5) out += abc[parseInt(bits.slice(i, i + 5), 2)];
return "mom_" + out.slice(0, 26);
};
console.log(momentId("https://example.com", "vid_8f2c", 12400, 31000));
// mom_rg2e4kdenkmkzilboihacumshnimport base64, hashlib
def moment_id(origin, asset_id, start_ms, end_ms):
raw = f"{origin}|{asset_id}|{start_ms}|{end_ms}".encode()
b32 = base64.b32encode(hashlib.sha256(raw).digest()).decode().rstrip("=").lower()
return "mom_" + b32[:26]
print(moment_id("https://example.com", "vid_8f2c", 12400, 31000))
# mom_rg2e4kdenkmkzilboihacumshn2. Add /.well-known/arv #
The manifest is where validators and agents start. At L1 it names your level, your license and your catalogs. Leave out tool profiles and keys until you offer them.
{
"arv": "1.0",
"conformance_level": "L1",
"publisher": {
"name": "Example Garage",
"contact": "agents@example.com"
},
"license_url": "https://example.com/license.xml",
"catalogs": [
"https://example.com/arv.json"
],
"schema": "https://agentreadyvideo.org/schema/1.0/manifest.schema.json"
}The file has no extension, so tell your host to serve it as application/json. On Vercel that is a headers entry in vercel.json; on Netlify, a _headers line; on GitHub Pages, keep a .nojekyll file so the .well-known folder is published.
3. Add JSON-LD Clip ids to the video page #
On each video page, describe the video as a schema.org VideoObject and each moment as a Clip. The Clip @id must equal the moment_uri and its url must equal the moment_url, so crawlers and agents name the same moment.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "VideoObject",
"@id": "https://example.com/videos/carb#video",
"name": "Tuning a carburettor",
"description": "How to set the idle mixture screw and check the idle speed.",
"thumbnailUrl": "https://example.com/poster/vid_8f2c.jpg",
"uploadDate": "2026-09-01",
"duration": "PT21M24S",
"hasPart": [
{
"@type": "Clip",
"@id": "arv:vid_8f2c#t=12400,31000",
"name": "Setting the idle mixture screw",
"startOffset": 12.4,
"endOffset": 31,
"url": "https://example.com/videos/carb#t=12.4,31"
}
]
}
</script>Do not put a stream or media file URL in this markup. Discovery finds moments; only a playback call starts them (forbidden-field rule). Emit a Clip only for moments whose rights allow segment display.
4. Add llms.txt and an RSL line #
Point language models at the manifest with llms.txt, then publish your license terms in RSL 1.0 and link them from robots.txt next to your sitemap.
# Example Garage videos
> How-to videos on engine repair. Agent-Ready Video (ARV) level L1.
## What this is
- Every moment is named arv:{asset_id}#t={start_ms},{end_ms} and listed in the catalog.
## Manifest
- https://example.com/.well-known/arv
## Tools
- None yet. Moments are listed in https://example.com/arv.json
## License
- https://example.com/license.xml (RSL 1.0). Credit Example Garage when you show a moment.
## Example questions
- How do I set the idle mixture screw on a carburettor?User-agent: *
Allow: /
License: https://example.com/license.xml
Sitemap: https://example.com/sitemap.xml<rsl xmlns="https://rslstandard.org/rsl">
<content url="/">
<license>
<permits type="usage">search ai-input ai-index</permits>
<prohibits type="usage">ai-train</prohibits>
<payment type="attribution"/>
</license>
</content>
</rsl>Use only RSL 1.0 usage words. Your sitemap must list the video page, and the page must return 200.
5. Run the validator coming #
The validator is not released yet. When it ships, one command runs the eight L1 checks against your live site or a local folder and prints pass or fail per standard.
npx arv validate https://example.com --level L1Until then, check by hand: /.well-known/arv returns JSON, every moment has start_ms < end_ms inside duration_ms, each id recomputes, and the Clip @id values match the catalog. The full list is in spec section 5.1.
Next steps #
Make it callable
Add an MCP endpoint with the origin profile and short-lived playback tokens.
Add rights and a ledger
Publish keys, sign playback tokens and usage receipts, and pass the negative tests.
Tell us it works
Built something that follows ARV? We list it on the implementations page once it passes.
Stuck or something unclear? Open an issue on GitHub or email team@agentreadyvideo.org.