I’ve vibe coded a GUI around the Visual Beat Meter workflow from the original Jupyter workbook here, which learns to spot a recurring visual pattern in a video — a “beat” — and exports the detected timestamps to a .funscript file., I’ve also made various quality of life improvements.
Requirements
-
Python 3.10+
-
Tkinter (bundled with the standard Windows / macOS installers; on Linux:
sudo apt install python3-tk) -
Packages:
pip install opencv-python numpy pillow scikit-learn
Run
python beat_scripter_gui.py
Workflow
The GUI is split into five tabs.
1. Setup. Pick the video and the output .funscript path. Enter start times in seconds, comma-separated (0, 90, 300, 540 — expressions like 1.5*60 work too). Choose how many frames to sample from each start time and which classifier to use.
2. Box Editor. Click and drag on the image to draw the bounding box, or type x/y/width/height directly. The box is in real pixel coordinates — the display is scaled to fit the window but the underlying crop uses the full-resolution frame.
3. Annotate. Step through the sampled frames with the box overlaid. Space marks the frame as not beat, B marks it as beat, ← goes back one frame. The buttons do the same if you prefer the mouse. A progress bar tracks how many of the loaded frames you’ve labeled.
4. Train / Predict. Train the model on your annotations, then predict beats across the whole video (or a frame budget, e.g. 15000 to test on the first ~8 minutes at 30fps). The prediction runs on a background thread with a cancel button.
5. Export. Writes the funscript. The output alternates positions 0 ↔ 100 on each detected beat, with a minimum 4-frame gap between actions to avoid jitter.
Tips
-
A small box (say 30×50 px) over a region with a clear two-state appearance trains fastest and predicts most accurately.
-
Annotate ~100 frames per section to start. If predictions are noisy, add more annotations rather than fiddling with the classifier.
-
KNN and Random Forest work well on raw pixels out of the box. SVM benefits from feature scaling, which this tool does not add by default.
-
For class-imbalanced data (much more “not beat” than “beat”), Random Forest tends to handle it more gracefully than KNN.
Code here:
Happy scripting!
A happy penis makes life feels tremendous.




