OpenFunML Release v0.3.1 (ML-Based Script Generation Extension for OpenFunscripter)

Release notes

0.3.1 - Fixed generated scripts landing a few frames early on videos whose video track does not start at 0:00.
0.3.0 - New model, VR Support, Shoulders, Vibration, etcs
0.2.1 - Fixes scripts that sat against the top or bottom for the whole video, and raises the default stroke amplitude to match human scripts. Same 0.2 model.

Links

Previous version: DeepFunGen 1.2.0 Release (Deep Learning–Based Funscript Generation)

Downloads: OpenFunML
Try in browser: OpenFunML Web (much slower, just for a quick look)

OFS: post / releases
OFS ng: post / releases

OpenFunML

An extension for ofs-ng and OpenFunscripter that generates funscripts
from video using a machine-learned model.

Windows only.
Uses a DirectX 12 GPU when present, otherwise falls back to the CPU, which is slow.

Notice

What this extension produces is not a finished script.
It gets the broad shape of the motion right, but the quality is not good enough to use as-is.
It is there so you do not start from an empty timeline.
Please do not upload generated scripts without editing them, so the community does not fill up with AI slop.

Install

Both extensions use the same engine.
Download the file that matches the editor you use.

File For
OpenFunML-ofs-ng.zip ofs-ng
OpenFunML-ofs.zip OpenFunscripter 3

ofs-ng — do not extract it. Go to Plugins → Install plugin from zip…,
pick the zip, and confirm the trust prompt.
To remove it: Plugins → OpenFunML → Uninstall…

OpenFunscripter 3 — extract it, then right-click install.ps1 →
Run with PowerShell. Restart OFS and enable Extensions → OpenFunML.
If the ps1 script does not work, copy the folder into the extensions folder by hand.

%APPDATA%\OFS\OFS3_data\extensions\OpenFunML

Using it

  1. Open a video in the editor.
  2. Plugins → OpenFunML (ofs-ng) or Extensions → OpenFunML (OFS 3).
  3. Pick a Model, leave Compute on auto.
  4. Run model and generate.

The keypoints land on the L0 (stroke) track.


The analysis is cached per video, so changing only the options takes about a second.
A different video or a different model triggers a full re-analysis.

Options

Option What it does
Max speed Units per second your device can reach. Human scripts run 542 at the 95th percentile, 670 at the 99th
Heatmap threshold Lower finds more peaks. The strongest control over stroke count
Prominence min Floor for peak detection. Raise it to ignore jitter in quiet sections
Stroke gain Scales each stroke around its own midpoint. Above 1.3 the median stroke becomes a full 0–100 swing (human scripts sit at 79)
Min stroke size Strokes smaller than this get widened, keeping their centre. 30 is the 10th percentile of human scripts
Anchor to position Keeps a fast stroke at the height the model saw it. Off, it drifts to the middle
Time offset ms Shifts every keypoint in time. Positive moves them later
Position min / max The range of values written to the script
Replace existing actions Off: generated actions are merged into the existing script

Terms for using the model

You may use the .onnx model in other programs as long as these hold:

  • the model filename is kept, and the model name is visible in the UI
  • not used in paid software

Credit is not required, but it is appreciated.

Checking issues

log.txt in the plugin folder holds the last run.

Editor Path
ofs-ng %APPDATA%\ofs\ofs-ng\plugins\OpenFunML
OFS 3 %APPDATA%\OFS\OFS3_data\extensions\OpenFunML

The program is unsigned, so antivirus false positives happen.
If SmartScreen blocks it, More info → Run anyway;
if Defender quarantines it, add the folder above as an exclusion.

8 Likes

Interesting how they AI all look alike heatmapwise oscillating around 50 not knowing right insertion. Quite sure this one also misses the turning point by 1-3 frames.

Welcome back and good to see more options for AI generation! I already thought the original DeepFunGen had some nice potential back when it released from my testing of it, although it felt more like a prototype back then. I think integration with the ofs-es is great given the FunGen editor is not open source. I hope this will continue to be trained and I’d like to see at this point a small competition between the various AI funscripter solutions!

2 Likes

I wondered about the timing issue described, I’ve seen it before, and in this instance my read is that this is a “motion model” and so has limited understanding but it’s a very cool little model, and I thought it was super interesting, especially when I ran inference on it; it was really close on the timing on many sequences.

I think I have this right, it takes 64 frames chunks of greyscale 256x256, they get some differencing processing, then convolutions to downsample it to something a Temporal Convolutional Network can comfortably process (with some normalization) and then the TCN crunches it and feeds it to the head. I think it looks like there’s also some further normalization that makes it tend to stretch each wave around the midpoint.

The prediction is driven by overall movement rather than understanding of what is moving and where. When it comes to humans moving, and the inertia, involved this tends to run into issues. e.g.

  • the male’s hips move frame upwards, but the female is moving down, then there’s a cancelling effect.
  • the valley is reached, but other body parts still move upwards (or downwards), which affect the models outputs causing delay.

Synthetic examples (not what it’d have been trained on) so shouldn’t be an indicator of performance, just of the tendencies:
preset_single
preset_unequal
preset_antiphase
edit, replaced mp4 with gif

It’s not always the case that there would be a delay, it’s possible it can be frame accurate, but if you’re going for frame accuracy you wouldn’t know which frames it missed timing on and would need to verify.

Disclaimer, I didn’t actually test the plugin, only the onnx model, because python packed into an exe and adding antivirus exclusions for it isnt something I do lightly. The plugin may have some extra wizardry that offsets the caveats described.

Sorry for barging in and infodumping, I just thought it was a very interesting and went down a rabbit hole. If I’ve gotten anything wrong, let me know and I’ll correct!

1 Like

Maybe the problem is the models see overall movement not a movement at a focused point. It looks like it.

1 Like

Not barging in at all!

Your read of the architecture is right. It takes 64 frames of 256×256 greyscale as one clip, hop 32, overlap-add. One thing to add: the frame differencing you spotted isn’t a preprocessing step, it happens inside the ONNX graph. That’s to stop the preprocessing spec from drifting between the training data loader and the actual app.

The convolutions that downsample aren’t only downsampling, there’s a Temporal Shift Module in them. One eighth of the channels get shifted one frame forward, one eighth one frame back, and the rest are left alone.

The encoder takes 256 down to 8×8, then a 1×1 projection to 192 channels, then global average pooling. After that pooling there is no spatial information left at all. What the TCN receives per frame is a single 192-dimensional vector, and it has no way of knowing where anything happened. So you’re right that it’s looking at overall movement rather than understanding what is moving and how, and that is a limitation of the model.

One thing I should correct is the midpoint stretching. That isn’t in the model, it’s postprocessing. stroke_gain defaults to 1.2 and scales each stroke around its own midpoint. There’s a fair bit of other postprocessing on top of that too. The difference you’re seeing between the raw model output and the plugin output comes from exactly there.

As for the exe, I completely understand. In most cases it should work without adding an antivirus exclusion. It’s hard to have easy distribution and peace of mind at the same time.

English isn’t my first language, so I had a generative AI translate this.

2 Likes

v0.3.0 Released

Model

  • Ships new model OpenFunML-0.3.onnx alongside 0.2.

VR video (new, off by default)

  • Reads 180° VR by taking one eye and flattening a window out of it. Previously a side-by-side frame was cropped through the middle, giving half of each eye with a seam between them.

Shoulders (new, off by default)

  • Adds a point either side of a slow peak, slightly below it, so the stroke reaches the end faster and lingers. The peak does not move, so amplitude is unchanged.

Vibration in pauses (new, off by default)

  • Adds a short flutter where stroking pauses briefly — a gap much longer than the surrounding rhythm, where the model still sees activity. Continuous stroking and long stops are left alone.

Changed defaults

  • Stroke gain 1.0 → 1.2, minimum stroke size 8 → 40.

Interface

  • Numbers are typed into input boxes instead of dragged — a slider could not reliably land on a round value.
1 Like

Just pushed 0.3.1. It fixes a bug where the generated script came out shifted slightly early on some videos the whole file, by the same amount.

If you’ve already generated scripts for those, regenerate them to pick up the fix.

BugFix

  • Fixed generated scripts landing a few frames early on videos whose video track does not start at 0:00.
1 Like

I dont feel this will ever work without using the human. Its pretty much 0 or 1 if a script is in sync or not. There may be slight variations but good scripters all set the turning points at the specific location. There always is a specific frame the motion stops or drastically changes. Then there is the vertical how much is it in. AI script generation fails in both vertical and horizontal in literally all points. This quite sets the quality of AI scripts, they are really bad compared to the standard. Time gained to make a perfect script - zero. What you all do is trying to make level 5 autonomous driving without the learning process. What you should do is assisted scripting like set the next point, fail and try again until the user acknowledges them all. Only after the scripters are done with the model and it can learn nothing more, there is chance for a software or addon for the crowd or non scripters that produces good scripts at least in easy and simple scenes maybe even HJ/BJ and still fail if overlapping no contact or choice problems with simultaneous moves.

Can the model learn? Meaning can you store data of what information the model gets fom a frame, what it wants to script and evaluate and where a good scripter has put the point to if at all? Could it do that frame wise or even up/down motion wise? Next motion it could use this knowledge and set the points accordingly and adapt?
Another approach would be the changes would be stored after an AI run. Showing the Ai it has put literally all points on the wrong position. Both could be used for before and after the AI run like: trying to set as human did compare to intended points and afterwards comparison, did it work as second check.

You’re right that the current architecture isn’t going to automate all of this.

The idea of learning from corrections inside the tool is a good one, but I’m doing this as a hobby rather than full time,
and building that loop properly looks like more time and effort than I can realistically put in.

What I’m doing right now is a lot simpler than that. I’m trying different things and hoping the model picks up not just where the points go, but the rules behind where a scripter puts a turning point.

On long occlusions a scripter keeps the rhythm going through them.
A model that only sees a few frames around the current one has no way to infer that, but I’m hoping that giving it a longer window gets it part of the way there.

If embedding that kind of information takes a much bigger model, or if it just isn’t reachable by training end to end, then I’m in the same position as an alchemist running experiments and hoping gold comes out. I work in software but not in machine learning, so I’m leaning on AI to get through this, and I honestly can’t always tell when I’m barking up the wrong tree.

is it possible to have a model trained per scene + action type. E.g. VR - bj / hj , VR - cowgirl, VR -missionary etc. The metadata can be set by the scripter with chapters and fed into the generation process.

Sure wasnt asking you to. I just put scripter guided AI generation on the table. Which could be a time saver and drastical quality changer.

Would an intermediate step in achieving something like that be integrating models like CoTracker v3 and SAM2 as interactive alternatives? I know these are very heavy models to run, however nobody to this day has produced a usable prototype tool that could use those models like an enhanced version of MTFG.

To my understanding of the capabilities of these models, they would solve almost all of the inherent issues with the simplistic MTFG approach, aside from when the scene changes drastically (e.g. camera angle changes or wacky screen effects). And it would allow a true co-scripting experience where the user selects the points and/or areas of interests and the min-max ranges of the sequence/chapter/camera angle, and then let the models figure the tracking out, notifying the user when tracking/confidence are lost. This approach should be universal no matter what video type or content type is scripted, albeit it would only be runnable by the top tier PCs for now.

The CoTracker 3 research/home page also offers alternative, lighter-weight models as well, that could be used by less powerful PC builds at the cost of maybe not being the best with occlusion or extensive scene changes/movements. Just an idea really. To this day I proposed this in two other places but both denied my request stating it was very hard to run, without showing any proof like recorded video or prototype build or something I could actually see or use on my rig (5080 + 9950x3D) to see for myself how computationally insane it is.

1 Like