Skip to content

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 ms
console.log(report.level, report.peakSpeed, report.issues);
const safe = makeSafe(result.script.actions); // same timing, no move too fast, no gap too short
const text = stringify({ ...result.script, actions: safe });
axisFromFilename('evening.twist.funscript'); // 'R0'
Terminal window
npm install @ananga-ai/funscript
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

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