Video
Upload videos, probe metadata, and extract frames as images into a dataset.
Pictograph annotates frames, not videos. The video resource handles upload and frame extraction; once extracted, frames are regular images you annotate with the standard SAM3 / annotation workflows.
Every example below shows the Python SDK call and the equivalent raw REST
request. The REST examples authenticate with an X-API-Key header; set
PICTOGRAPH_API_KEY in your shell to copy-and-run them.
from pictograph import Client
client = Client() # reads PICTOGRAPH_API_KEY
upload
Three-step upload (signed URL → PUT → return path), same pattern as images. The SDK gets a signed URL, then PUTs the bytes directly to GCS.
| Arg | Type | Default | Notes |
|---|---|---|---|
local_path | str | Path | required | Local video file |
content_type | str | "video/mp4" | Set for non-MP4 sources |
info = client.video.upload(
"./recording.mp4",
content_type="video/mp4",
)
print(info.gcs_path, info.gcs_uri)
# Step 1: request a signed upload URL + temp gcs_path.
curl -s -X POST "https://api.pictograph.io/api/v1/developer/video/upload-url" \
-H "X-API-Key: $PICTOGRAPH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"filename": "recording.mp4", "content_type": "video/mp4"}'
# Step 2: PUT the bytes directly to the returned upload_url (no API key — the
# signed URL carries its own signature).
curl -s -X PUT "<upload_url>" \
-H "Content-Type: video/mp4" \
--data-binary @./recording.mp4
Returns VideoUploadInfo (gcs_path, gcs_uri, upload_url). Pass
gcs_path to probe() and extract_frames(). Supported codecs: anything
ffmpeg can demux (H.264, H.265, VP9, AV1, etc.).
probe
Inspect a video’s metadata without extracting frames. Pass the
gcs_path returned by upload(). The backend downloads the bytes once
and runs ffprobe, so it is slow on large files — call it once, never poll.
meta = client.video.probe(info.gcs_path)
print(meta.duration_seconds, meta.native_fps, meta.width, meta.height)
print(meta.frame_count)
curl -s -X POST "https://api.pictograph.io/api/v1/developer/video/probe" \
-H "X-API-Key: $PICTOGRAPH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"gcs_path": "<gcs_path-from-upload>"}'
Returns VideoMetadata (duration_seconds, native_fps, width,
height, frame_count) from a server-side ffprobe invocation.
extract_frames
Extract frames from a video into the destination dataset as images.
Frames are decoded at sample_fps, written under
{dataset}/{parent_folder_path}/{folder_name}/, and registered in
project_images with SigLIP embeddings spawned automatically.
| Arg | Type | Default | Notes |
|---|---|---|---|
dataset_name | str | required | Destination dataset (project name) |
gcs_path | str | required | Source video from upload() |
folder_name | str | required | Virtual folder created for the frames |
sample_fps | float | 1.0 | Frames per source second (0–60) |
parent_folder_path | str | "/" | Parent folder for the new folder |
wait | bool | True | Poll until terminal |
job = client.video.extract_frames(
dataset_name="my-dataset",
gcs_path=info.gcs_path,
folder_name="frames",
sample_fps=2.0, # extract 2 frames per second of source video
parent_folder_path="/raw-footage",
wait=True,
poll_interval=3.0,
timeout=1800.0,
)
print(job.status, job.frames_extracted)
curl -s -X POST "https://api.pictograph.io/api/v1/developer/video/extract-frames" \
-H "X-API-Key: $PICTOGRAPH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"dataset_name": "my-dataset", "gcs_path": "<gcs_path-from-upload>", "folder_name": "frames", "sample_fps": 2.0, "parent_folder_path": "/raw-footage"}'
Each extracted frame becomes a regular Image row — ready for
annotation, search, and training.
sample_fps=1.0 is the cheapest setting; sample_fps=30.0 extracts every
frame of a 30 fps source. Frame extraction does not consume credits —
you pay only for the storage of the resulting images.
get_extraction / wait_for_extraction
Poll a kicked-off job (use these when you called extract_frames(wait=False)).
job = client.video.get_extraction(job_id)
job = client.video.wait_for_extraction(job_id, timeout=600.0)
curl -s "https://api.pictograph.io/api/v1/developer/video/extract-frames/{job_id}" \
-H "X-API-Key: $PICTOGRAPH_API_KEY"
Returns VideoExtractionJob (status, progress, frames_extracted,
total_frames, folder_path).
Common errors
| Status | Exception | Cause |
|---|---|---|
| 404 | NotFoundError | gcs_path missing / not yours, or dataset_name invalid |
| 400 | ValidationError | Backend couldn’t parse the file as a video |
| 408 | PollTimeoutError | Long videos may exceed default timeout |