From Veo to Motion Transfer: Building Demo Videos for a BJJ Training App
DEV Community

From Veo to Motion Transfer: Building Demo Videos for a BJJ Training App

My BJJ coach told me daily HIIT was the fastest way to build match stamina, so I built BJJ FLOW - a solo-training app for Brazilian Jiu-Jitsu with BJJ-specific drills, a mat-side timer, demo videos for every move, and fully offline voice guidance.

The plan was to generate all the demo videos with AI. It worked for push-ups. It completely failed for the hip escape - the most basic movement in BJJ - because the model had simply never seen it. The fix was to film myself performing every move and transfer the motion onto a virtual athlete with Wan 2.2, plus a small pile of OpenCV/ffmpeg post-processing. This is the full build story. (Original articles in Japanese: Zenn / note)

Why this app exists

BJJ movement is weird. Shrimping across the mat, sprawling to stop a takedown, guard work with your legs - none of it maps to running or standard gym work, and neither do the muscles or the breathing.

Doing BJJ-specific HIIT alone every day sounds simple until you try it: watch the clock, decide the next drill, remember the correct form, manage the intensity - all while you're already gassed. It takes more willpower than the workout itself.

So the design goal was narrow: put your phone next to the mat, tap once, and just move. BJJ FLOW gives you:

  • BJJ-specific HIIT menus (from 4-minute Tabata-style sessions): hip escapes, sprawls, triangle movements, technical stand-ups
  • Mobility and stretching for the hips and lower back - the areas BJJ players actually complain about
  • An oversized timer readable from across the mat, with color-coded work/rest intervals
  • Voice guidance so you never have to look at the screen mid-round
  • Demo videos for every move, looped, with slow playback and pause for form checks
  • Custom routines: pick your drills, set work/rest seconds, save your "10 minutes before morning class"

Step 0: Hypotheses and analytics before features

I'm an SRE by trade, and the failure mode I wanted to avoid is the classic indie one: build what I want, discover nobody uses it. Before writing features, I wrote down 11 hypotheses in KaizenLab (a hypothesis-tracking tool I also build): retention by belt color and training frequency, reasons users would switch from a generic timer, whether people feel the stamina change in sparring, willingness to pay for a one-time Pro plan, habit-formation rates.

Then I designed the Firebase Analytics (GA4) events before the screens: workout_start, workout_complete, mat_feedback, paywall_view, plus user properties like belt color and injury-concern areas. Instrumentation first, features second - so every later decision could be checked against numbers instead of vibes.

Design: Write the concept down, then let AI rebuild the UI

The first prototype had 4 tabs and looked like a generic fitness app. But this app is used at the edge of a mat, mid-workout. Decoration and deep navigation are liabilities.

So I wrote the concept into documents (concept.md, screens.md) before touching code:

  • Concept: "MAT SIDE COMPANION"
  • Background: warm charcoal #10120F
  • Colors with jobs: lime #C5F467 for primary actions, mint #8ADCB8 while working, amber #F59E0B while resting
  • Type: an oversized monospace timer you can read from a distance
  • Explicitly excluded: neon, flames, game-style effects

With the concept and screen specs written down, I handed them to an AI design/coding tool (GPT Astra) and had the Flutter UI rebuilt in one pass - all 18 screens, down to an app icon based on a BJJ belt forming the letter "F".

The lesson wasn't "AI is good at design". It's that AI output quality is bounded by how precisely you can state the concept in text first.

The video problem, part 1: Veo is great - at movements it has seen

Every drill needed a demo video, all performed by the same virtual athlete in the same rash guard. My first pipeline:

  1. Generate a starting-pose still of the athlete (gemini-3-pro-image)
  2. Feed it to Veo 3.1 (veo-3.1-fast-generate-preview), specifying that the first and last frames should match, to get an 8-second loop
  3. Convert with ffmpeg to 960×540 H.264 and bundle it in the app with a poster image

Each move got a JSON spec describing head, torso, arms, legs, and contact points over time, processed by a generation script (generate_move_videos.py).

For standard movements - push-ups, squats, planks, mountain climbers - the output was genuinely natural. Even the triangle choke hip thrust and the technical stand-up came out well with detailed keyframe instructions.

Then came groundwork. The hip escape (shrimping), the reverse shrimp, the sit-through, 90/90 hip stretches: the model collapsed. These movements barely exist in video training data. No matter how precisely I prompted - "support the body on the lower shoulder and upper foot, drive the hips back and away", with negative prompts like "do not stand up, do not bridge" - it produced a person curling up on their side, or just standing up.

You cannot prompt your way around a movement the model has never seen.

The video problem, part 2: Film yourself, transfer the motion

So I inverted the pipeline. If the AI doesn't know the movement, perform it yourself and let the AI copy the motion. I switched to motion transfer with Wan 2.2 (Wan2.2-Animate on fal.ai): it reads the skeleton and motion from a source video and redraws it onto the reference athlete.

This made filming the most labor-intensive part of the whole project. My daughter shot me on a phone at home and at the dojo - hip escapes, sit-throughs, breakfalls, stretches, a dozen-plus source videos. For the model to read a movement correctly: camera perfectly side-on, whole body in frame, one clean rep with no wasted motion. Any wobble in my performance became a wobble in the athlete. Many retakes, much sweat.

Raw transfer wasn't shippable either. The post-processing pipeline that made it work:

  • Stabilization (OpenCV): lock the footage to the first frame - handheld shake makes the transferred athlete sway
  • Background greying (MediaPipe): extract a person mask and paint the background grey, so furniture and clutter aren't misread as limbs or props
  • Slow it down, then speed it back up (ffmpeg): fast moves like breakfalls outrun the model, so I interpolated frames (minterpolate), slowed to 0.5× for transfer, then restored 2× speed
  • Freeze-frame repair: the transfer output stalled for a frame roughly every 0.8 seconds; a script detects repeated frames by inter-frame difference and fills them by linear interpolation (fill_repeats)
  • Loop seam removal: measure brightness difference between first and last frames and crossfade so loops don't jump

Honest limitation: motion transfer still isn't perfect. Early users have told me some move videos don't look quite right - and they're correct. The pipeline gets niche movements mostly there; closing the last gap in accuracy is ongoing work, and it's the top item on my list.

Voice: Pre-generated, fully offline

Mid-workout you can't stare at a screen, so the app talks: exercise names, countdowns, "10 seconds left". OS text-to-speech sounds different on every device and follows the device's language settings.

Instead I pre-generated every cue with Gemini TTS (voice: Charon), directed as "a calm, low-voiced sports coach: clear, natural, short, no shouting", via a batch script (generate_voice.py). Files are converted from WAV to AAC at 32kbps to keep the app small.

Result: no API key in the app, identical voice quality on every device, and it works in a basement dojo with no signal.

What I took from this build

Hypotheses and instrumentation before features. It kept the build from wandering.

Write the concept down before asking AI to generate. The design tokens and rules in text form are what made the AI-generated UI coherent instead of random.

Know each model's boundary, and route around it instead of arguing with it. Text-to-video for movements in its training data; motion transfer for movements that aren't.

The breakthrough wasn't a better prompt - it was accepting that the most "AI" project I've shipped was unlocked by me, on the floor, doing hip escapes in front of a phone camera held by my daughter.

BJJ FLOW is live - details and download links are on the product page. If you train BJJ and try it, I genuinely want to hear which drills to add and which videos still look wrong.

I'm toshipon - an SRE and indie hacker in Japan, founder of BUILD GEEKS. I build my apps (BJJ FLOW, Focusnest) hypothesis-first and write up the process. If you're building something similar, or want a hand with the AI pipeline side of a product, DM me on X.

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.