Sign in Get started

Video

Upload videos, probe metadata, and extract frames as images into a dataset.

View as Markdown

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.

ArgTypeDefaultNotes
local_pathstr | PathrequiredLocal video file
content_typestr"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.

ArgTypeDefaultNotes
dataset_namestrrequiredDestination dataset (project name)
gcs_pathstrrequiredSource video from upload()
folder_namestrrequiredVirtual folder created for the frames
sample_fpsfloat1.0Frames per source second (0–60)
parent_folder_pathstr"/"Parent folder for the new folder
waitboolTruePoll 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

StatusExceptionCause
404NotFoundErrorgcs_path missing / not yours, or dataset_name invalid
400ValidationErrorBackend couldn’t parse the file as a video
408PollTimeoutErrorLong videos may exceed default timeout
Copied to clipboard