Client Lambda API

The browser client calls the Lambda (lambda-resize) HTTP API for operations that require full frames or video: get-frame, get-movie-data (playback URL), tracking, rotate-and-zip, start-processing, new-frame. The VM (Flask/gunicorn) does not run tracking, serve frames, or serve movie playback URLs.

See ArchitectureDesign.md for the three principles: frames/video → lambda-resize, HTML → flask_app, metadata → flask_api.

Lambda API base URL

The server injects the Lambda API base URL into every page via base.html so it is available to all JavaScript as the global LAMBDA_API_BASE:

  • Set in the template from get_lambda_api_base() (see apikey.page_dict()).

  • Example value: https://your-lambda-api.example.com/

  • If not configured, the variable is empty and client code should skip Lambda calls (e.g. show “Lambda URL not configured”).

All client calls to the Lambda API are authorized: the client sends api_key (and other parameters) in the request; the Lambda validates api_key (e.g. via DynamoDB) before performing the operation.

Endpoints used by the client

Operation

Method

Path / body

Purpose

Get frame

GET

/api/v1/frame?api_key=...&movie_id=...&frame_number=...&size=...

Single frame as JPEG

Get movie data

GET

/api/v1/movie-data?api_key=...&movie_id=...&format=zip or format=json (optional)

Default: 302 redirect to signed S3 URL (movie). format=zip: 302 to zip. format=json: 200 JSON { "movie_id", "url" (MP4), "zip_url" (if present) } for playback or download links.

Status

GET

/status

Health check

Track movie

POST

/api/v1

Body: { "action": "track-movie", "api_key", "movie_id", "frame_start" }

New frame

POST

/api/v1

Body: { "action": "new-frame", "api_key", "movie_id", "frame_number", "frame_base64_data"?(optional) }

Rotate and zip

POST

/api/v1

Body: { "action": "rotate-and-zip", ... }

Start processing

POST

/api/v1

Body: { "action": "start-processing", ... }

Tracking

Tracking is requested by POSTing to LAMBDA_API_BASE + 'api/v1' with JSON body:

  • action: "track-movie"

  • api_key: from the logged-in user (same as other API calls)

  • movie_id: movie to track

  • frame_start: the edited source frame (0-based). PlantTracer preserves this frame, deletes stored annotations for frame_start + 1 ... end, and resumes tracing at the following frame.

The Lambda validates api_key, resolves user_id, then runs tracking (writes trackpoints and zip to DynamoDB/S3). The client then polls for completion (e.g. via Flask get-movie-metadata with get_all_if_tracking_completed) and updates the UI.

Where the variable is set

  • Template: src/app/templates/base.html — declares const LAMBDA_API_BASE = "{{ lambda_api_base }}";

  • Server: src/app/apikey.pypage_dict() sets lambda_api_base from get_lambda_api_base() so every page that uses the base template gets the same global.