I save everything: notes, PDFs, screenshots, voice recordings, useful videos, and random links I’m definitely going to need again someday.

The problem is that saving something and finding it again are two completely different things.

So I finally built the app I’ve wanted for ages: a private system that can process almost any kind of media and let me search across all of it.

Xiaohei fishing one exact timestamp out of a crowded archive

The spare Mac became the server

I have a spare M1 Mac with 64GB of RAM, so I turned it into a self-hosted AI and media server for my family.

The system has two main parts:

  • A local engine downloads, processes, stores, indexes, and searches everything.
  • Minimono is the app my family actually uses to add things and search the archive.

Each person gets their own tenant-isolated archive and agent. They all run on the same Mac, but their files, searches, and conversations are separated by tenant and workspace-bound API keys.

One shared Mac with separate locked tenant archives

You can throw almost anything into it

Right now it accepts:

  • Notes
  • Normal web links
  • PDFs
  • Images
  • Voice recordings
  • Uploaded videos
  • YouTube videos, including Shorts
  • X/Twitter posts containing video

You paste a link or upload a file, and the app handles the rest in the background.

The original is kept, processing happens asynchronously, and the item becomes searchable once the useful parts have been extracted and indexed.

TikTok support is next.

How I keep signed-in video downloads working

Some YouTube and X videos only download reliably with a signed-in session, so I run a small macOS background agent that handles the required cookies.

It takes a scoped snapshot from a selected Brave profile while the browser stays open, refreshes only the configured YouTube/Google and X/Twitter domains in a separate automation profile, and securely pushes separate YouTube and X cookie sets to the engine every 15 minutes.

The pairing credential is stored in macOS Keychain. The setup screen only previews cookie names and metadata—not their values—and cookie values and tokens are kept out of status files and logs.

Different media needs different processing

There isn’t one magical model that understands everything. Each type of media goes through its own pipeline.

For audio and video, I use Whisper Small Q8 to generate a transcript with timestamps.

Images and sampled video frames go through a local OCR model, so text shown on screen becomes searchable too.

For semantic text search, I use EmbeddingGemma 300M Q8. It turns notes, transcripts, PDF text, OCR results, and other extracted content into embeddings stored in a local LanceDB index.

Visual search uses two models:

  • SigLIP 2 connects language and images, so a text query like “red mountain” can match a video frame.
  • DINOv3 is better for finding visually similar objects or scenes from another image.

Using both gives me two ways to search: describe what something looks like, or provide an image and find visually related frames.

All of those models run locally on the Mac.

Xiaohei cranking four specialised local models over one media source

Search returns the actual evidence

I didn’t want a search engine that just returned the title of a two-hour video.

If I search for something like:

life

The engine searches the transcript, original and translated subtitles, OCR, notes, document text, and the rest of the archive.

If the word appears three minutes into a video, the result includes that timestamp. Clicking it opens the video at the matching moment.

This is what that looks like in practice: one search, three sources, and twelve exact matches across a document and two videos.

Search results for “life” showing a document excerpt and timestamped matches across two videos

Visual search works in a similar way. I can search for:

red mountain

The query is embedded in the same visual space as the sampled video frames, so the system can find a matching frame even if nobody ever said “red mountain” in the video.

It can also search text shown inside a video frame through OCR.

That distinction matters: the result isn’t just “this video might be related.” It’s “this particular moment is why the video matched.”

Xiaohei tying a long filmstrip into one exact matching moment

The same flow works on mobile

The iPhone app searches the same archive and returns the same timestamped evidence. A result for “life” shows the matching frame, excerpt, and exact moment instead of making me scrub through the whole video.

Tapping a result opens the video at that timestamp, with the matching transcript line highlighted underneath. Search, playback, captions, and seeking all stay connected on mobile.

Mobile search results for life with matching video frames and timestamps
Search results include the matching frame, excerpt, and timestamp.
Mobile video player opened at 12:56 with the matching transcript line highlighted
Tapping a result opens the video at the exact matching line.

Translation keeps the original timing

The engine can translate audio and video captions while preserving the original cue IDs and timestamps.

That means switching languages doesn’t break navigation. A translated subtitle result can still take you back to the exact moment in the original video.

The translation system supports preset languages as well as custom target languages. I’m planning to extend the same experience more broadly across notes and documents.

Here it is on mobile with Cantonese selected: the translated captions keep the same timestamps, and the active line stays connected to the current moment in the video.

Mobile video player showing Cantonese subtitles and a timestamped translated transcript
Cantonese captions and the translated transcript stay aligned with the original video timeline.

The archive also powers a personal agent

The engine also has an archive-backed chat system, so each tenant can ask questions about their own saved material.

Before answering, the agent searches that tenant’s archive and attaches the relevant citations to the response. It’s closer to asking questions about your own memory than chatting with a model that knows nothing about what you’ve saved.

The whole system is designed to run 100% locally, including the generative parts. Chat, translation, summaries, and descriptions can all be routed through a local OpenAI-compatible model.

  • Original files stay on my Mac.
  • Transcripts, OCR, embeddings, visual indexes, and the archive stay local.
  • Search and media processing run locally.
  • The personal agents can use local models too.

I also structured the generation layer so I can switch those jobs to my signed-in Codex subscription. That part is optional, but it’s faster than the local models I’m running today, especially for chat, translation, summaries, and descriptions.

When I turn that on, only the selected text or context needed for the task is sent to Codex. The original files, indexes, search system, and archive still stay on the Mac.

So the local setup is the complete system. Codex is just a faster lane when I want it, not the storage layer or a required backend.

Xiaohei passing only selected context out of the locked local archive

Why tenant isolation mattered

Since this is for my family, I didn’t want everyone sharing one giant search history and archive.

Each person gets an API key bound to their own tenant and workspace. That workspace becomes the ownership boundary for files, entries, embeddings, searches, and agent conversations.

So everyone can use the same hardware and my shared inference setup without searching through each other’s stuff.

It feels like each person has their own private media library and personal agent, but I only have one machine to maintain.

The part I like most

The app isn’t really about collecting more information. We already have far too much of that.

It’s about making the things we’ve already seen useful again.

A video is no longer just a link. It becomes a searchable collection of spoken moments, subtitles, visible text, and visual frames.

A voice note becomes searchable text.

A PDF becomes part of the same archive as a YouTube video.

A screenshot stops being something that disappears into the camera roll.

Everything becomes another piece of searchable memory.

There’s still plenty I want to add: TikTok ingestion, broader translation, better support for scanned PDFs, and richer visual search across standalone images.

But the core idea is working now: throw something into the archive, let the Mac process it, and find the exact piece you need later.