Nodes are the atomic processing steps of MetaLoom. A pipeline is a graph of nodes, and Cortex workers execute the individual node tasks that Loom dispatches. Each node has a unique kind (name) used to reference it in a pipeline definition and to route its work to a worker that can run it.
A node writes its result back to Loom over the REST API — a typed component plus an
asset_node_result ledger row. Downstream nodes do not name the node they depend on: they connect to
one of its ports. A port has a name that is local to its node, a content type that says what it
carries, and a cardinality that says whether it carries one element or a sequence of them.
Between them the built-in nodes cover any media file type — images, videos, audio and documents. What is actually analysed for a given asset depends entirely on which nodes the pipeline contains.
|
Tip
|
Every node listed below is also in the interactive pipeline editor on this site, which needs no server and no account. Drag a few onto the canvas to see which ports will connect to which — the editor enforces the same type rules Loom does, so a wiring it rejects is one a real pipeline would reject too. |
Every node page opens with a diagram of that node in a pipeline: what flows in on the left, what comes out on the right, and a tab per alternative configuration. Hover any port — or tap it, or reach it with the keyboard — for a card giving its content type, its cardinality, and what the value actually is. A stacked marker on a port means it carries a sequence rather than a single element. The key below covers both the type icons and the cardinality:
The built-in nodes fall into four categories.
Hashing & Deduplication
| Node | Applies to | Purpose |
|---|---|---|
Hashing ( |
Any file |
Content hashes for identity and deduplication |
Fingerprint ( |
Video |
Perceptual video fingerprint for similarity search |
Consistency ( |
Video, Audio |
Detect incomplete / corrupt media |
Deduplication ( |
Any / Video |
Detect and move duplicates |
Extraction & AI
| Node | Applies to | Purpose |
|---|---|---|
Asset Metadata ( |
Image, Document, Audio, Video |
Read the metadata already inside a file — title, creator, keywords, date, rights and GPS position |
Tika ( |
Any |
Extract format metadata + text with Apache Tika |
OCR ( |
Image |
Extract text with Tesseract |
VLM ( |
Image |
Read images with a vision-language model; olmOCR document transcription |
Speech-to-Text ( |
Video, Audio |
Transcribe audio with Whisper |
Text-to-Speech ( |
Any (text connected to its |
Synthesize narration audio (Orpheus/Kartoffel DE, Kokoro EN) |
Sentiment Analysis ( |
Any (text connected to its |
Score the tone of extracted text (German and English) |
Translate ( |
Any (text connected to its |
Translate extracted text into a target language with a language model |
Content Guard ( |
Any (text connected to its |
Screen content against a harm taxonomy with a guardrail model, and gate a branch on the verdict |
LLM Enrichment ( |
Any |
Enrich metadata with a language model — one output port per prompt |
Captioning ( |
Image, Video |
Natural-language captions for images and videos |
Image Generation ( |
Image |
Generate images from a prompt (or remix the asset) with a diffusion model |
Video Generation ( |
Image |
Generate a short video clip from a prompt (or animate the asset’s image) with a diffusion model |
Face Detection ( |
Image, Video |
Detect faces + embeddings — its |
Object Detection ( |
Image, Video |
Detect objects with YOLO — its |
Face Description ( |
Image |
Describe detected faces with a vision model, one description per face |
Segment Anything ( |
Image, Video |
Turn boxes into exact outlines with SAM 2 — segment everything, cut out what a detector found, or track a mask through a clip |
Depth Map ( |
Image |
Estimate how far each part of a photo is from the camera |
Scene Layout ( |
Image (a depth map and detections connected) |
Work out what is in front of, behind or next to what |
Media Analysis
| Node | Applies to | Purpose |
|---|---|---|
Thumbnail ( |
Video |
Contact-sheet preview thumbnails |
Quality ( |
Image, Video |
Resolution / blurriness / bitrate metrics |
Scene Detection ( |
Video |
Optical-flow scene boundaries |
Dominant Colour ( |
Image (optionally with detections connected) |
Work out which colours a picture is made of, as HEX and in words (English and German) |
Watermark ( |
Image, Video |
Stamp your own logo or mark onto the asset at a relative position — the original is never modified |
Image Manipulation ( |
Image (optionally with detections connected) |
Straighten by EXIF orientation, crop, reframe to a target ratio (including the blurred vertical-video fix) and resize — the original is never modified |
Pipeline
| Node | Applies to | Purpose |
|---|---|---|
Filesystem Source ( |
— (source) |
Enumerate media from disk |
S3 Source ( |
— (source) |
Enumerate media from S3-compatible object storage, picking up only what changed |
Google Drive Source ( |
— (source) |
Enumerate media from Google Drive, picking up only what changed — including renames and moves |
OneDrive Source ( |
— (source) |
Enumerate media from OneDrive or a SharePoint library, picking up only what changed |
Filter ( |
— (routing) |
Route each item down one branch per configured bucket — the output port is the branch |
Tag ( |
Any |
Attach tags from rules over what upstream nodes worked out — a tagged asset is a findable asset |
Script ( |
Any |
Run your own code as a pipeline step and emit declared ports — list outputs fan out |
S3 Sink ( |
Any |
Upload produced files to an S3 bucket and register them as assets — its |
Move ( |
Any local file |
Relocate the file to a folder, a storage pool, a library or an S3 bucket — never overwriting, and only removing the original once the destination is verified |
Assign ( |
Any known asset |
Add the asset to a collection or a library. Writes the membership only; it never touches the file |
Requirements at a Glance
Most nodes are pure CPU. A few need a native library or an external model service:
| Requirement | Nodes |
|---|---|
OpenCV / video4j native runtime |
|
InspireFace native runtime (GPU optional) |
|
YOLO native runtime + an ONNX model (GPU strongly recommended for video) |
|
Whisper runtime (whisper.cpp; GPU optional) |
|
Tesseract (Tess4J) |
|
An LLM provider service |
|
A vision-language model service |
|
A TTS sidecar (Orpheus/Kartoffel + Kokoro) |
|
A SAM 2 sidecar (GPU strongly recommended) |
|
An image-generation sidecar (SDXL-Turbo / diffusion model; GPU recommended) |
|
A video-generation sidecar (LTX-2; a 24 GB GPU is required) |
|
A sentiment sidecar (german-sentiment-bert + twitter-roberta; CPU is enough) |
|
A depth sidecar (Depth Anything V2 Small; CPU is enough, GPU is much faster) |
|
The |
|
S3-compatible object storage (AWS S3, MinIO, Ceph) |
|
Google Drive, OneDrive or SharePoint credentials |
|
A reachable OpenAI-compatible language model endpoint |
|
A reachable OpenAI-compatible endpoint serving a guardrail model (Llama Guard, ShieldGemma or Granite Guardian) |
|
CPU only |
|
Pin the heavy kinds to dedicated or GPU workers via CORTEX_NODE_WHITELIST — see
Cortex Configuration.
Processing Capabilities
What the built-in node set gives you, and which node provides it:
- Relocation and disposal
-
moveis the one node that changes where an asset’s bytes live — a trash folder, a storage pool, a library, or an S3 bucket for cold storage. It refuses to overwrite, works out whether a destination is on another disk before it starts copying, and only removes the original after the destination has been verified.assignis its counterpart for curation: it files an asset into a collection or a library and never touches the file at all. - Asset hashing
-
md5,sha256,sha512,chunk-hashrun in parallel over any file. Hashes are the basis for exact deduplication and for skipping already-processed assets. - Video fingerprinting
-
fingerprintcomputes a perceptual multi-sector fingerprint using thevideo4j-fingerprintlibrary. It survives transcoding, resolution changes and minor edits, which makes near-duplicate detection possible at scale via vector similarity search. - Face detection
-
facedetectfinds faces in images and video with the InspireFace library, returning bounding boxes, facial embeddings and the optimal focal point for cropped thumbnails. Itsdetectionsport carries one element per face, sofacedescription,scene-layoutanddominant-colorall work per face simply by connecting to it. - Object detection
-
objectdetectfinds objects — people, vehicles, animals, furniture — in images and video frames with a YOLO model, reporting each as a labelled box with a confidence score. The classes it can report come from the model’s own vocabulary, so choosing the model is choosing what the library can be searched for. Itslabelsport lists the distinct classes found and connects straight totag, which turns every asset into something searchable by what is in it. - Segmentation
-
sam2answers the question detection cannot: not where a thing is, but which pixels are it. Given the boxesobjectdetectalready found, it returns each one as an exact outline; given nothing at all, it finds every distinct region in the picture by itself; given a video, it follows an outline from frame to frame as the subject moves. That boundary is what separates a product from its backdrop, crops to a person rather than to a rectangle around one, and turns "how much of this shot is sky" from an impression into a number. - Thumbnail generation
-
thumbnailrenders contact-sheet previews from video frames and source images and uploads them to Loom as asset binaries. - Metadata ingest
-
metadatareads what a file already says about itself — the photographer’s title, caption and keywords, the camera and exposure, the licence and credit line, and where the shutter was pressed — out of EXIF, IPTC, XMP, companion.xmpfiles, PDF and Office properties and audio tags, and normalises all of it onto one Dublin Core shape. It records which original field supplied each value, so nothing has to be trusted blindly, and it needs no model and no GPU. Itstextoutput carries the authored prose alone, ready fortranslate,sentimentorllm. - Document text extraction
-
tikauses Apache Tika to pull the full text out of any supported document format. It is the companion tometadata: one gives you the words, the other the properties. - Scene detection
-
scene-detectionsplits video into scenes with an optical-flow detector, producing cut timestamps that can drive per-scene thumbnails or clips. - OCR and speech-to-text
-
ocrextracts text from images and document pages with Tesseract;vlmtranscribes document pages with a vision-language model such as olmOCR, which keeps the layout — tables, columns, formulas — that plain glyph recognition flattens;whispertranscribes audio and video soundtracks with the Whisper model. - AI captioning and enrichment
-
captioninggenerates natural-language descriptions of both images and videos with a vision-language model — images from a still frame (SmolVLM), videos from their temporal content (Qwen2.5-VL), optionally as a per-scene timeline — andllmenriches metadata through an LLM provider such as llama.cpp or vLLM. - Image generation
-
imagegengenerates a new image with a diffusion model behind a small HTTP sidecar — either from a text prompt or by remixing the asset’s own image — and writes the PNG to the worker’s local cache. - Video generation
-
videogengenerates a short video clip with a diffusion model behind a small HTTP sidecar — either from a text prompt or by animating the asset’s own image as the opening frame — and writes the MP4, with a synchronised audio track, to the worker’s local cache. - Watermarking
-
watermarkstamps a logo or mark you supply onto an asset at a relative position, so one setting works across a library of mixed resolutions. Stills are composited in-process; video goes through theffmpegoverlay filter, which re-encodes the picture but copies the audio through untouched. The original file is never modified — the marked copy is a new artifact. - Image manipulation
-
image-manipulationstraightens, crops and reframes a picture in one pass — applying its EXIF orientation so it is upright, cutting it to a fixed region or one built around the faces connected to itsdetectionsport, forcing a target aspect ratio (padding vertical pictures with a blurred enlargement of themselves rather than black bars), and bounding the result’s size. No model or external tool is needed, and the original file is never modified. - Text-to-speech
-
ttsturns text connected to itstextport — anllmsummary, a caption, or a translated transcript — into narration audio, using Orpheus/Kartoffel for German and Kokoro for English behind a small HTTP sidecar. - Sentiment analysis
-
sentimentscores the tone of text the pipeline already produced — connect document text, OCR output, a caption or an LLM answer to itstextport — as positive, neutral or negative with a signed polarity value, using dedicated German and English models behind a small HTTP sidecar. - Translation
-
translateturns text the pipeline already produced into another language — connect a transcript, document text or an OCR result to itstextport and the translation comes out ontranslation, ready forttsto speak. One node translates into one language, so several languages means several nodes; each translation is stored under its own language and stays separately retrievable. Documents longer than the model’s context window are split at paragraph and sentence boundaries, never mid-sentence, and rejoined. - Content screening
-
guardchecks content against a harm taxonomy — connect a transcript, document text, an OCR result or a caption to itstextport, or point it at image assets — and answerssafeorunsafewith a confidence score and the categories that fired. Itssafeoutput is a branch, so a publishing or upload step connected behind it runs only for the items that came back clean, while flagged assets are still fully processed and their verdicts stored for review. Three families of open guardrail model are supported behind the one node — Meta’s Llama Guard, Google’s ShieldGemma and IBM’s Granite Guardian — and all of them are normalised onto one shared vocabulary of harm categories and one comparable score, so changing the model does not mean rewiring the pipeline. Llama Guard 4 and ShieldGemma 2 read pictures directly; the rest screen text. - Depth and spatial layout
-
depthmapworks out how far each part of a photo is from the camera, from the photo alone, andscene-layoutuses that to say how the detected things relate — which is in front, which is behind, which one hides part of another. Together they turn a flat list of boxes into a scene you can caption accurately and search spatially. - Colour analysis
-
dominant-colorworks out which colours a picture is actually made of — the whole frame, a fixed region, or every box arriving on itsdetectionsport — and reports each one as HEX, RGB, HSL and CIELAB alongside a name a person would use, in English and German. It needs no model and no GPU, so it can run over an entire archive cheaply. - Consistency checking
-
consistencyvalidates that stored metadata — hashes, dimensions, codec information — still matches the file on disk, flagging inconsistencies for review or remediation. - Cloud drive ingest
-
gdrive-sourceandonedrive-sourceread media straight out of Google Drive, OneDrive and SharePoint, without anyone having to copy it to a disk or a bucket first. Both are differential: a re-run asks the drive what changed and processes only that, so watching a large drive costs a single request when nothing has happened. And because a file in a drive keeps its identity when someone renames it or files it away, both report a move as a move rather than as a deletion followed by a fresh upload — so the metadata you have already built up stays attached to it. - Automatic tagging
-
tagattaches tags from rules you configure over what the pipeline already worked out — a quality metric, a transcript, a list of colour names. It matters because of where a tag lands: most analysis results sit on the asset where you can read them but not search them, while a tag becomes part of the asset’s search document as soon as it is written. A vocabulary can be pinned to an allowed list so automatic tagging cannot litter the shared tag list, and the node only ever removes a tag it can prove it wrote itself. - Branching a pipeline
-
filtersorts items into buckets you configure and grows one output port per bucket, plus anotherport for everything else. The port is the branch: anything wired to a port that carried nothing is skipped for that item, and the skip carries on down that branch — so one node routes a pipeline any number of ways without a condition repeated at every step. Today it sorts by language, decided by a language model.
Authoring Your Own Node
Cortex is designed to be extended, but there is no drop-in plugin mechanism: the node set of a Cortex
process is wired at build time through Dagger modules, so the shipped cortex-server image serves
exactly the built-in kinds listed above. Running a node of your own means building your own Cortex
instance that includes it. A worker announces the node kinds its factory has registered when it
registers with Loom, so a custom instance becomes dispatchable as soon as it connects, and it can run
alongside the stock workers — which keep serving the built-in kinds.
A custom node in Java is three steps:
-
Extend
AbstractMediaNode<YourOptions>. -
Implement
name(),isProcessable()andcompute(). -
Expose the node from a Dagger module, include that module in your instance’s node collection, and register the node kind with the pipeline node factory.
The examples/ directory of the source repository carries the complete, working setup rather than a
sketch: cortex-custom-node holds the node with its options, payload and Dagger module;
cortex-custom assembles the daemon that includes that module and connects to a Loom backend; and
cortex-python implements a minimal worker in Python that speaks the wire protocol directly, for
logic you would rather not write in Java. See Cortex Examples for the code
and the build and run commands.