# The pipeline What av-club is meant to do, and — just as importantly — what has not been decided yet. **None of this is built.** This document exists so the decisions get made deliberately rather than being settled by whatever gets written first. Where something is open, it says so. ## The problem Someone uploads a file. It might be: - a 12 MB photo straight off a phone, 4000px wide, in HEIC - a 4K video in a codec Safari will not play - a JPEG carrying the GPS coordinates of the room it was taken in - a file named `photo.jpg` that is actually a PNG, or a PDF, or nothing at all - something enormous, uploaded by accident What a page needs is none of those: a few sizes in a modern format, a poster frame for video, dimensions known ahead of time so layout does not shift, and nothing embedded that the person who uploaded it did not mean to publish. ## What it should do ### 1. Identify, do not trust Establish what a file **actually is** by inspecting it, never from its extension or the `Content-Type` a browser attached. A rejected upload should say something a non-technical person can act on, not a MIME type. ### 2. Strip what should not travel GPS coordinates, camera serial numbers, timestamps, editing history. `sharp` drops these by default on re-encode — see `docs/TOOLING.md`. Video metadata needs the same treatment and is not free. ### 3. Probe, and keep the numbers Width, height, duration, codec. These get stored, because knowing an image's aspect ratio before it loads is what lets a page reserve the space and not shift as it arrives. ### 4. Derive Images: a small number of widths, in a modern format, never upscaled past the original. Video: something every browser plays, plus a poster frame. ### 5. Name outputs so they can be cached forever Content-addressed or otherwise unique, so a derivative can be served `immutable` honestly and replacing an image never serves a stale one from a cache. ## What is NOT decided These are real forks. Picking one by accident is how a project ends up with an answer nobody chose. ### How a consumer talks to this | Option | Consequence | |---|---| | **A library** the consumer imports | Simplest. Processing happens in the web server's process — a big video transcode blocks a worker and competes for CPU with page rendering. | | **A CLI** the consumer shells out to | Clean isolation, no shared runtime. Every call pays process startup, and errors arrive as exit codes and stderr rather than as values. | | **A service** the consumer calls | Scales and isolates properly. It is another thing to deploy, monitor and secure, which is real work for a small site. | ### Whether processing is synchronous Does an admin wait for a 4K video to transcode while staring at a spinner, or does the upload return immediately and the derivative appear later? Asynchronous is better for them and means a job queue, a way to show "still processing", and a decision about what a page renders in the meantime. Synchronous is far simpler and is fine for images; it is not fine for video. **These two questions are related** — a queue implies something long-lived, which pushes toward a service. ### Where output goes Not decided, and it interacts with the consumer's deployment: whether a deploy replaces the working directory determines whether generated files can live inside it at all. This is currently an open question in `fofos/platform` too. ### The derivative ladder Which widths, which formats, what quality. Deliberately unanswered — it should follow from a real design, and guessing produces sizes nobody uses and gaps where one was needed. ### Externally hosted media A consumer may store a URL to a video hosted elsewhere rather than a file. Whether av-club has anything to say about those — probing them, fetching poster frames, or ignoring them entirely — is not decided. ## Principles worth keeping **The original is never destroyed.** Derivatives are derivatives. A quality setting judged wrong in six months should be re-runnable, and it cannot be if the source was thrown away. **Rejections explain themselves.** The person uploading is not a developer. "That file is 180 MB; the limit is 50 MB" is usable. "Unsupported media type" is not. **Verify by running, not by asserting.** `scripts/verify.sh` is the existing example: it encodes a video and reads it back rather than checking a version string. The same standard applies to the processing code.