Funscript, explained
A funscript is a small timing file that tells a device what to do, moment by moment, while a video plays. It's the format the interactive-script community has standardised on — if you've downloaded a script for a video, you've downloaded a .funscript.
This page covers what's actually inside one, how to play and make them, and one thing that's newly possible: cutting a video to a script you already have, instead of scripting a video you already have.
What's actually in a funscript file
It's plain JSON. Strip away the metadata and it's a list of timestamped positions:
{
"actions": [
{ "at": 0, "pos": 0 },
{ "at": 480, "pos": 90 },
{ "at": 960, "pos": 10 }
]
} at is milliseconds from the start of the video. pos is a position from 0 to 100. That's essentially the whole format — everything else is convention layered on top.
Two consequences worth understanding, because they explain a lot:
- A script is tied to one specific video file. The timestamps only mean anything against the exact cut they were written for. A different release of the same scene will drift.
- Intensity lives in the speed, not the position. A script sitting at
pos: 90isn't "intense" — it's parked. Fast alternation between positions is intense. This is why heatmaps colour by speed, and it matters later on this page.
How to play one
You need a player that reads the script and drives a device. The usual options:
- Desktop players that load a video plus its matching
.funscriptfrom the same folder — the standard setup is that the script has the same filename as the video. - Device-specific apps from the hardware makers themselves.
- Browser players on sites that host scripted content.
The near-universal convention: keep video.mp4 and video.funscript side by side, same name. Most players find the script automatically that way.
How scripts get made
Three approaches, roughly in order of effort:
- By hand, in an editor. OpenFunscripter (OFS) is what most scripters use — you scrub the video and place points. Slow, accurate, and the way good scripts still get made.
- Motion tracking. Tools that follow movement in the video and generate points from it. Decent starting point, usually needs cleanup.
- From a beat grid. For anything music-timed — PMVs, cock hero, HMVs — the timing is the music, not the on-screen motion. If you can detect the beats, you have the script skeleton.
That third one is worth expanding, because it's the case most people on this site are in.
Making a script from a song's beats
For music-timed video, hand-tapping beats is the tedious part — hundreds of placements before you make a single creative decision. Beat detection solves that in one pass.
Onset Engine will export any track's detected beat grid as a funscript directly (also as an Audacity label track, or CSV if you'd rather do your own thing with it):
OnsetEngine.exe export-beats song.mp3 You get a metronome-pattern script — a stroke on every detected beat, with downbeats identifiable — that you load into OFS as a timing skeleton and then shape. It's free in the demo and not paywalled. There's more detail on that, and on the community around it, in the Eroscripts guide.
The other direction: cutting a video to a script
Here's the part almost nobody does, because until recently there wasn't a tool for it.
Normally you have a video and you write a script for it. Flip that around: you have a script you like — maybe one you wrote, maybe one you downloaded for a scene you own — and you want a new edit built around its rhythm. The script becomes the blueprint instead of the output.
Onset Engine can take a funscript as the energy curve for an edit:
OnsetEngine.exe render job.json --final --energy-curve script.funscript What that actually does: it reads the script's stroke speed over time — remember, speed is the intensity signal, not position — and uses that as the edit's intensity envelope. Where the script goes fast, the edit cuts fast and reaches for your highest-energy clips. Where it eases off, the edit breathes.
The cuts still land on the music's beat grid, so the result is still beat-synced and still looks deliberate. What the script controls is pacing and clip intensity, not raw cut placement. You can also blend it against the music's own energy rather than replacing it outright:
--energy-curve script.funscript --energy-curve-weight 0.5 And if you'd rather draw the curve yourself, it takes a plain CSV of time_s,intensity instead — a hand-drawn build, a curve exported from something else, whatever you can express as intensity over time.
Why you'd actually want this
- You have a script you love. Build a fresh edit that follows its shape, rather than re-scripting from scratch for new footage.
- Cock hero rounds. The escalation pattern is an intensity curve. Draw it once as a CSV, get an edit that follows it.
- Script and video from one source. Export the beat grid, shape it into a script, then drive the edit from that same curve — the video and the script can't drift apart, because they came from the same timing.
Honest limits
- This doesn't write motion for you. Onset reads a script's intensity; it doesn't watch a video and generate stroke points. Motion-tracking tools do that, and this isn't one.
- Beat export is a skeleton, not a finished script. It gives you accurate timing. The feel is still your job.
- Scripts are cut-specific. Driving an edit from a script produces a new video with its own timing — the original script won't line up with the result. They're related in shape, not frame-for-frame.
Try it on a script you already have
Beat export and energy curves are both in the free Onset Engine demo — watermarked at 720p, no card needed. Runs entirely on your machine.
Try Onset Engine or try the free demo first - no credit card neededRelated
- Eroscripts guide — the scripting community, and free beat export
- Cock hero maker — rounds, escalation, beat meters
- What's new in Onset Engine — energy curves shipped in v1.0.7
- Free driver pack — tuned PMV / HMV / cock hero / hypno drivers
- Pacing & energy curves — how intensity shapes an edit