YouTube videos.insert: 256 GB limit and containsSyntheticMedia
The YouTube Data API videos.insert method takes files up to 256 GB and a status.containsSyntheticMedia flag. A request body for an AI-made upload, with checks.

The YouTube Data API accepts uploads up to 256 GB through videos.insert, with MIME types video/* and application/octet-stream, and lets you declare AI-made content with status.containsSyntheticMedia in the same request body. For short clips the size limit is irrelevant; the flag is the part that needs a decision on every upload. This is a body example plus a guard that stops you uploading a Sume-generated file without a declaration.
Facts from the method page
| Item | Value |
|---|---|
| Maximum file size | 256 GB |
| Accepted MIME types | video/*, application/octet-stream |
| Synthetic media flag | status.containsSyntheticMedia in the request body |
| Quota note on the page | 1 unit in the Video Uploads quota bucket, with a stated 100 calls per day |
| Shorts | Not mentioned on this page |
Request body with the flag
The body below sets the declaration from your own record of how the file was made. Keep that record in your pipeline: whether the video came from a Sume model, a trim of one, or neither. Cutting or captioning a real recording does not make it synthetic on its own, but that is your call and YouTube's policy, not Sume's.
def insert_body(title, made_with_ai, privacy="private"):
if made_with_ai is None:
raise ValueError("decide containsSyntheticMedia explicitly")
return {
"snippet": {"title": title[:100]},
"status": {
"privacyStatus": privacy,
"containsSyntheticMedia": bool(made_with_ai),
},
}
print(insert_body("Product demo", made_with_ai=True))
Producing the file
If the upload came out of Sume, store the job id next to the file. Video trim ($0.02 per job) and video captions ($0.20 per clip up to 60 seconds) each return a new MP4 URL, so the provenance of every upload is one job id away.
A pre-upload guard
Make the declaration a required argument, as the function above does, so no code path can upload without someone having decided. The decision itself is simple to record at creation time: when a job id from a generation endpoint produced the file, mark it true; when a person filmed it, mark it false; when you cannot tell, stop. Because the guard raises on None, a forgotten flag fails in your tests instead of on a published video.
Limits
The quota wording on the page reads oddly (a per-day call count next to a unit cost), so confirm your own quota in the Google Cloud console rather than planning from this table. We did not verify here which uploads YouTube requires you to label, or what happens when the field is omitted; read the YouTube policy page for that. For the field in more depth, see containsSyntheticMedia when uploading an AI video.
Sources
Related posts
More in Developers
- YouTube API uploads stuck private: unverified project rule
Videos uploaded through videos.insert from an unverified API project created after 28 July 2020 are locked private. Test one upload before a Sume batch.
- Zed prevent_idle_sleep for agent threads and Sume jobs_wait
Zed 1.21 keeps your machine awake while agent threads run. A sleeping laptop is not a cancelled Sume job: jobs keep billing, so resume with jobs_wait.
- 20-minute Reel narration vs Sume's 20,000-character TTS limit
Instagram allows Reels up to 20 minutes. Sume TTS accepts 1 to 20,000 characters per request. A rough estimate of how much narration one request covers.
- 40-clip montage Reel: how Timeline chunks a render past 12 slots
Timeline 1.0 accepts up to 200 slots and chunks automatically past 12; forcing single is refused. What that means for a fast-cut Reel and its $0.10 per minute.
Written by Sume