Fair hit — "loop-cut the segments" was doing a lot of hiding in that sentence. Seamless is the whole difficulty, and "use your favorite tool" was a cop-out. So I've pushed the tooling I'd been using privately:
build_idle_loop.py— runs MediaPipe over the take, measures eye-openness per frame, finds the blink minima, then picks the blink→blink window that maximizes eyes-open time and pose match. The cut point lands on a closed eye, so the loop's seam is invisible. Pingpong fallback when there's no clean blink pair, plus it records the head-frontal "settle times" the player uses to time expression reveals.cut_emotions.py— contact sheet to spot the neutral valleys in a multi-emotion take, then cuts and web-encodes them into per-emotion segments.validate_preset.py— PASS/FAIL gate on structure, assets, and emotion coverage.
Plain Python + ffmpeg + MediaPipe, no notebook yet, but they should run anywhere.
On the default avatars: you're right, and I don't have a good defence. The blocker isn't code — it's that an avatar is a pile of clips someone has to actually render, and right now I only have the one I built for myself. A small free starter preset is the obvious next move; I just haven't made it. Until then it's genuinely "bring your own," which is a fair thing to hold against it.
Small correction to my own comment: the emotion clips were actually made with Gemini i2v — 3 emotions per generation, which is exactly why
cut_emotions.pyexists (it cuts the take at the neutral valleys).LivePortrait is the free local route and it does work — the project's earlier expression library was built with it, and it gives you one clip per driving video, so you skip the cutting step entirely. I've fixed the README to state both instead of implying LivePortrait was the path I'd personally taken.