:::roboflow.core.project
Project.upload_video sends the original MP4 or MOV bytes to a signed upload
URL. It creates a video Source in the project; it does not extract frames or
run inference. The platform processes the upload asynchronously.
project = rf.workspace("my-workspace").project("my-actions")
status = project.upload_video(
"clip.mp4",
batch_name="session-1",
tag_names=["indoor"],
metadata={"camera": "front"},
split="train",
)
if status["status"] == "pending":
status = project.wait_for_video_upload(status["videoId"], poll_timeout=300)
if status["status"] == "failed":
raise RuntimeError(status["message"])
source_id = status["videoId"] # Use this Source ID for video annotations.upload_video(..., wait=True) performs the bounded wait in one call. The
returned status is the API response: pending, uploaded (with
resolvedBatch), or failed (with message). Poll later with
project.get_video_upload_status(video_id). Always use videoId from the
final uploaded response because ingestion can deduplicate onto another
Source. Batch, tags, metadata, and split follow the platform upload API;
the API validates their values. A timeout leaves the upload running, so
poll its original ID later. poll_timeout=0 makes one status request and
returns a terminal result if available. Status requests use the remaining
polling budget as their connection and read inactivity timeout; this is not
a strict whole-response wall-clock limit for a slowly streaming server.