Library: @ananga-ai/funscript
@ananga-ai/funscript reads, checks and repairs .funscript files. It has no dependencies and runs anywhere JavaScript runs. It is the same code as the checker on ananga.ai. MIT licence.
import { parse, check, makeSafe, stringify, axisFromFilename } from '@ananga-ai/funscript';
const result = parse(await file.text());if (!result.ok) throw new Error(result.error);
const report = check(result.script); // default limits: 500 units/s, 80 msconsole.log(report.level, report.peakSpeed, report.issues);
const safe = makeSafe(result.script.actions); // same timing, no move too fast, no gap too shortconst text = stringify({ ...result.script, actions: safe });
axisFromFilename('evening.twist.funscript'); // 'R0'npm install @ananga-ai/funscriptReference
Section titled “Reference”| Function | Returns | What it does |
|---|---|---|
parse(textOrValue) |
{ ok: true, script } or { ok: false, error } |
Parses JSON text or a value; accepts a byte-order mark |
check(script, limits?) |
Report |
Points, start and end, strokes, average and peak speed, and every problem with a plain-language message |
normalize(actions) |
Action[] |
Valid points only, sorted, clipped to 0–100, one point per time |
invert(actions) |
Action[] |
0 becomes 100 |
offset(actions, ms) |
Action[] |
Moves every point in time; points before 0 are dropped |
mergeClose(actions, minGap = 80) |
Action[] |
Merges points closer than minGap ms, keeping the extremes |
capSpeed(actions, maxSpeed = 500) |
Action[] |
Shortens moves that are too fast without changing timing |
makeSafe(actions, limits?) |
Action[] |
normalize, then mergeClose, then capSpeed |
stringify(script) |
string |
One action per line, the layout editors use |
positionAt(actions, ms) |
number or null |
Position at any time, by straight-line interpolation |
axisFromFilename(name) |
'L0'…'A2' |
evening.twist.funscript → R0; plain names → L0 |
stemFromFilename(name) |
string |
The media name a script pairs with |
The report
Section titled “The report”check() never throws. Its level is ok, warning or error, and each issue has a code, a severity, a count, up to five example indexes and a message you can show as is.
| Code | Severity | Meaning |
|---|---|---|
no-actions |
error | Nothing to play |
bad-point |
warning, or error above 5% of points | A point lacks a number for at or pos |
negative-time |
warning | A point falls before the media starts |
out-of-range |
warning | A position is outside 0–100 |
unsorted |
warning | Points are out of time order |
duplicate-time |
warning | Two points share a time |
too-fast |
warning | A move is faster than maxSpeed |
too-close |
warning | A point comes less than minGap ms after the previous one |
inverted |
warning | The script is marked inverted |
partial-range |
info | range is set below 100 |
long-pause |
info | The device holds still for more than 10 s |