Talks while she thinksnew
Replies stream in and she speaks them a sentence at a time, so the first words are out while the model is still writing the rest. Each sentence is lined up on the audio clock so there is no gap between them.
She lives on your desktop in a transparent window. Talk to her or type, and she answers in her own voice, lip syncing and acting out what she writes. You can cut her off mid sentence, and sometimes she starts the conversation.
This is the real app interface running in your browser, with the same renderer, lip sync and gestures as the desktop version. Her window is transparent, so she stands over whatever is behind her.
Replies on this page are recorded lines in her real voice, picked by keyword. The desktop app answers with a live language model, hears you through the microphone and lets you talk over her.
She is written as a friend and not an assistant. She has opinions, a TikTok edit she will not stop complaining about, and permission to be busy or just not help.
Replies stream in and she speaks them a sentence at a time, so the first words are out while the model is still writing the rest. Each sentence is lined up on the audio clock so there is no gap between them.
The mic stays open while she talks, so interrupting her is just talking over her. Only what she actually said goes in the transcript, so her next line follows from what you heard.
She has her own thing going on and will bring it up now and then without being asked. It is rate limited, stays quiet at night, and there is a switch for it in the tray.
When the model writes *tilts head* it gets cut out of the speech and played as an animation, timed to the point in the audio where it was written. Between replies she shifts, glances and settles on her own.
Loudness sets how far her mouth opens and the balance between the first two formant bands picks one of five shapes, so it changes with the vowels. Sibilants get damped so every "s" does not look like a shout.
The model already has spring bones. A simulated breeze leans the direction each joint falls, so the physics does the work and long strands swing further than short ones.
Facts worth keeping get pulled out of your conversations and fed into later ones. Say "remember that" and it is saved straight away, whether or not the model noticed.
She can set a timer, read what you just copied, open a link or write something down. She knows the time, which app you are in and when your battery is low. She looks at your screen only when you press the button.
Point her at any OpenAI compatible model. Mine runs on a GPU server over an SSH tunnel, and if that goes quiet she falls back to a small model on the Mac and tells you she did.
Kokoro, an 82M parameter voice model, running on the laptop's CPU at about three times realtime. Two voicepacks are blended for her tone and then pitched up a semitone without changing the timing.
Oh, you're back. I was just about to give up on that transition.
Yeah no, I'm busy losing a fight with the borrow checker.
Forty takes on one transition. Forty. The algorithm better appreciate this.
Your voice never leaves the machine in either direction. I checked by watching the bridge's connections through a full conversation. The only text that leaves goes to whichever model you point her at, so with Ollama on the same Mac nothing leaves at all.
| Stays on the Mac | Leaves the Mac | |
|---|---|---|
| Microphone audio | Transcribed locally | Never |
| Her voice | Synthesised locally | Never |
| Conversation and memory | Saved to disk here | |
| What you said, as text | Sent to your model | |
| Clipboard, when she reads it | Sent to your model, and you can turn it off | |
| Screenshots | Only when you press the button | Sent to your vision model |
It needs a Mac. I built and tested it on an M2 MacBook Air with 8 GB of RAM.
Keep it at ~/marina. Desktop, Documents and Downloads are protected by macOS, and the app hangs with no error if it lives in one of them.
git clone https://github.com/skep13/marina ~/marina cd ~/marina && ./setup-mac.sh
The easiest option is Ollama on the same Mac. Copy the example config and set base_url to your Ollama address.
ollama pull llama3.2:3b cp character_config.example.yaml character_config.yaml # base_url: "http://127.0.0.1:11434/v1"
Export a VRM from VRoid Studio (a .vroid project file will not load) and put it at app/models/model.vrm, or pick one with the person button once the app is open.
This makes Marina.app, puts it in Applications and starts her backend for you. The first reply is slower while the speech and voice models load.
./build-app.sh
| Talk | ⌘ ⇧ Space to start and again to stop, or the mic button |
| Cut her off | Talk over her, or ⌘ ⇧ . |
| Hide or show | ⌘ ⇧ H |
| Quit from anywhere | ⌘ ⇧ Q |
| Buttons | Hidden until you hover over her, so she looks clean the rest of the time |
A MacBook Air with 8 GB of RAM. Every number below was taken on it, and that limit shaped the whole design.
| Speech to text | 0.98 s for 8.5 s of audio with Faster-Whisper base.en on the CPU |
| Text to speech | 3.3x realtime once warm with Kokoro 82M on the CPU |
| Between sentences | 0.00 ms gap, because each one is scheduled on the audio clock |
| Language model | about 55 tok/s with Qwen3-VL 8B on my GPU server, or 37 to 44 tok/s with llama3.2:3b on the Mac |
| Full turn, warm | about 1.5 s from message to speech |
| Avatar | 53k triangles, 20 MToon materials and 195 spring joints, drawn at display refresh |
| Memory footprint | about 1.5 GB for the bridge, renderer and avatar together |