Architecture design principles¶
Three principles govern where logic lives:
All frames and video processing → lambda-resize
Operations that need full frames or video (get-frame, tracking, rotate-and-zip, start-processing) run only in the Lambda (lambda-resize). The VM (Flask/gunicorn) does not decode video, extract frames, or run tracking.All HTML → flask_app
All HTML pages and templates are served by the Flask app (flask_app.py). There is no other HTTP server serving HTML for the main app.All metadata → flask_api
Movie and user metadata (get-movie-metadata, put-frame-trackpoints, edit-movie, set-metadata, list movies, etc.) go through the Flask API (flask_api.py). The VM owns DynamoDB writes for metadata; Lambda writes metadata only as a result of its own processing (e.g. after rotate-and-zip or tracking).
Get-movie-data and new-frame on Lambda¶
get-movie-data (GET /api/v1/movie-data) returns a 302 redirect to a signed S3 URL for the movie (or zip if format=zip). For video playback the client uses format=json and gets 200 JSON { "movie_id", "url", "zip_url" } (url = MP4, zip_url = zip if present), then sets the video element’s src to url so the browser loads the stream directly from S3 (redirects are not followed for cross-origin media).
new-frame (POST /api/v1 with action: "new-frame") accepts client-supplied frame image data (base64) and writes it to S3 and DynamoDB for a future “create your own timelapse” flow. The VM does not serve this; Lambda handles it for consistency.
References¶
Client → Lambda: ClientLambdaAPI.md
Processing flow: ProcessingPhases.rst
Movie metadata and first frame: movie_player.rst