[RFC] Single-file multi-axis

There could be yes, but the device and player will handle the limits. If the device can pitch 360 degrees (god save you) then the player/firmware 0-100 will map to 0-360. Its a bit to much to ask of funscript to know the device limits. Also R0 can be 360, 270 or 180 or even 140 depending on the hardware. Its impossible to know before hand.

The best thing to keep in mind is these values are relative and they dont need to be exact. If the scripter wants to target specific hardware thats up to them.

.zip should work in MFP but it has a drawback of not being a funscript file so you wont be able to play it in anything else and you will have to unzip.

The merged files on eroscripts right now should work since MFP v1.32.0. You should go to your eroscripts settings and disable the .max option so that the merged funscript is a simple .funscript.
Or you can add max to the funscript names of L0 in MFP.

1 Like

It’s off by default (afaik, at least should be, if it’s not tell me), and the .max option recommends naming videos .max so you know they are multi-axis without checking funscipt

We have to open the funscript anyways to parse it. May as well check for the tracks object while we are in there.

On DeoVR all I see is the video file extension (I dont see scripts), thats my use case

You’re not parsing the file contents? I’m not sure what you’re doing exactly.
Adding this to XTP I could see a value in the extension but only for upfront multi axis detection so the XTP can put it in the multi axis category. I will have to parse every funscript at least once to detect it.

Im not sure its worth mixing the old multi-file standard with this.

Especially when the existing funscript standard specifies the videoname matches the funscript name.
Adding .max to the main funscript breaks that backwards compatibility for existing players that are not multi axis.
That is the strongest reason to not change the file name that I can think of.

I think @Dimava adds .max to his videos so that the .max is visible in the file list in DeoVR.
But that does not really have anything to do with funscript. You could as well add [multiaxis] to the front of your videos, or just make a folder only for multiaxis scripts.

1 Like

btw @Yoooi thoughts on time formats?
I don’t like at in ms, duration in seconds and startTime in hh:mm:ss
Can we choose one please

I use startAt/endAt internally because I use then with at for processing

But durationTime may be better and more obvious

It probably should have been in ms, an oversight in the discussions while OFS was implementing chapters/bookmarks.
But you can’t suddenly change it now, so it is what it is. Making some changes on a thread does not make it a reality, you need a popular scripter software to implement it first.

That’s why I propose a parallel durationTime or startAt


Here are the stats on stuff usage btw:

β”Œβ”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚    β”‚ key                    β”‚ appear β”‚ appear% β”‚ value                                                                                                   β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  0 β”‚ version                β”‚ 27797  β”‚ 98.29%  β”‚ "1.0" (27540), 1 (231), null (23), "1.1" (2), "0.1.0" (1)                                               β”‚
β”‚  1 β”‚ inverted               β”‚ 27797  β”‚ 98.29%  β”‚ false (27786), "false" (7), "true" (3), true (1)                                                        β”‚
β”‚  2 β”‚ range                  β”‚ 27798  β”‚ 98.30%  β”‚ 100 (24026), 90 (3699), 99 (55), 50 (8), "100" (4), 85 (2), 0 (1), 71 (1), 95 (1), 101 (1)              β”‚
β”‚  3 β”‚ actions                β”‚ 28280  β”‚ 100.00% β”‚ "array" (28280)                                                                                         β”‚
β”‚  4 β”‚ metadata               β”‚ 24130  β”‚ 85.33%  β”‚ null (121), {"bookmarks":[],"chapters":[], (78), {"creator":"","description":"" (69), {"creator":nul    β”‚
β”‚  5 β”‚ metadata.creator       β”‚ 23867  β”‚ 84.40%  β”‚ "" (13420), "shbek" (705), "99DM" (516), "BeaB" (397), "Procedurally generated using  (396), "falafe    β”‚
β”‚  6 β”‚ metadata.description   β”‚ 23753  β”‚ 83.99%  β”‚ "" (20968), "https://github.com/ncdxncdx/F (396), "Hi! I'm Korean scripter!\nI'm (373), "Scripted by    β”‚
β”‚  7 β”‚ metadata.duration      β”‚ 23795  β”‚ 84.14%  β”‚ 60 (145), 180 (118), 120 (105), 200 (92), 0 (91), 210 (91), 216 (89), 141 (78), 173 (78), 30 (76), 1    β”‚
β”‚  8 β”‚ metadata.license       β”‚ 23644  β”‚ 83.61%  β”‚ "" (18803), "Free" (4459), "Paid" (275), "None" (88), "free" (11), "free! No commercial use allow (6    β”‚
β”‚  9 β”‚ metadata.notes         β”‚ 23646  β”‚ 83.61%  β”‚ "" (21798), "It is not enough to say thank (257), "Thx to my patrons!\n\nκΉ€μ£Όμ•ˆ, Di (192), "NiL" (88),  β”‚
β”‚ 10 β”‚ metadata.performers    β”‚ 23766  β”‚ 84.04%  β”‚ [] (21376), ["Anime girl"] (114), [""] (31), ["bustypuppy"] (21), ["Stacy Cruz"] (20), ["Earesistibl    β”‚
β”‚ 11 β”‚ metadata.script_url    β”‚ 23634  β”‚ 83.57%  β”‚ "" (20485), "https://www.patreon.com/beksc (659), "https://www.patreon.com/99DM" (435), "www.patreon    β”‚
β”‚ 12 β”‚ metadata.tags          β”‚ 23859  β”‚ 84.37%  β”‚ [] (19963), ["music","audio"] (550), ["hentai"] (241), ["Anal"] (130), ["Hentai"] (126), ["VR"] (113    β”‚
β”‚ 13 β”‚ metadata.title         β”‚ 23816  β”‚ 84.21%  β”‚ "" (8715), "The Gambling's Paradise [Kari (28), "The Gambling's Paradise [Yume (20), "lapsi_scene2_1    β”‚
β”‚ 14 β”‚ metadata.type          β”‚ 23637  β”‚ 83.58%  β”‚ "basic" (22993), "" (644)                                                                               β”‚
β”‚ 15 β”‚ metadata.video_url     β”‚ 23675  β”‚ 83.72%  β”‚ "" (20929), "https://dezyred.com/games/a-d (21), "https://vrbangers.com/video/l (15), "https://badoi    β”‚
β”‚ 16 β”‚ bookmark               β”‚ 3220   β”‚ 11.39%  β”‚ 0 (3181), 2555881560 (2), 31200000 (1), 31999968 (1), 32800000 (1), 109275615 (1), 120666546 (1), 17    β”‚
β”‚ 17 β”‚ lastPosition           β”‚ 3222   β”‚ 11.39%  β”‚ 0 (101), 226559893 (4), 602602602 (4), 1909576241 (4), 1910243575 (4), 8878878870 (4), 333667 (3), 4    β”‚
β”‚ 18 β”‚ graphDuration          β”‚ 3222   β”‚ 11.39%  β”‚ 50000000 (2268), 300000000 (288), 60000000 (37), 10000000 (28), 58142008 (20), 41666666 (18), 144675    β”‚
β”‚ 19 β”‚ speedRatio             β”‚ 3221   β”‚ 11.39%  β”‚ 1 (1780), 0.5 (80), 0.3 (78), 0.98 (56), 2 (49), 0.46 (42), 0.52 (38), 0.24 (38), 0.48 (36), 0.4 (35    β”‚
β”‚ 20 β”‚ injectionSpeed         β”‚ 3222   β”‚ 11.39%  β”‚ 350 (3053), 400 (57), 700 (15), 340 (13), 450 (9), 410 (7), 510 (6), 330 (5), 430 (5), 460 (5), 200     β”‚
β”‚ 21 β”‚ injectionBias          β”‚ 3222   β”‚ 11.39%  β”‚ 0 (3172), 10 (12), 5 (11), 15 (6), 50 (6), 20 (3), 2.5 (3), 7.5 (2), 30 (1), -5 (1), -2.5 (1), -20 (    β”‚
β”‚ 22 β”‚ scriptingMode          β”‚ 3219   β”‚ 11.38%  β”‚ 0 (2396), 1 (535), 3 (139), 5 (116), 2 (24), 4 (9)                                                      β”‚
β”‚ 23 β”‚ simulatorPresets       β”‚ 3221   β”‚ 11.39%  β”‚ [{"name":"Simulator 1","fullRa (809), [{"name":"Simulator 1","fullRa (106), [{"name":"Simulator 1","    β”‚
β”‚ 24 β”‚ activeSimulator        β”‚ 3222   β”‚ 11.39%  β”‚ 0 (3185), 1 (30), 2 (7)                                                                                 β”‚
β”‚ 25 β”‚ reductionTolerance     β”‚ 3214   β”‚ 11.36%  β”‚ -0.1 (2498), 7.5 (614), 5 (10), 10 (8), 2.5 (8), 5.9 (5), 5.1 (4), 4.8 (4), 3.9 (4), 8 (3), 6.3 (3),    β”‚
β”‚ 26 β”‚ reductionStretch       β”‚ 3214   β”‚ 11.36%  β”‚ 187500 (3157), 250000 (12), 212500 (6), 125000 (4), 72500 (3), 175000 (3), 217500 (3), 35000 (2), 62    β”‚
β”‚ 27 β”‚ clips                  β”‚ 3213   β”‚ 11.36%  β”‚ [] (3199), [{"name":"Clip 1","start":0,"e (2), [{"name":"Clip 1","start":0,"e (2), [{"name":"Clip 1"    β”‚
β”‚ 28 β”‚ rawActions             β”‚ 3192   β”‚ 11.29%  β”‚ "array" (3191), "null" (1)                                                                              β”‚
β”‚ 29 β”‚ metadata.bookmarks     β”‚ 13341  β”‚ 47.17%  β”‚ [] (12020), [{"name":"","time":"00:00:13.0 (11), [{"name":"","time":"00:00:34.0 (10), [{"name":"","t    β”‚
β”‚ 30 β”‚ metadata.chapters      β”‚ 13254  β”‚ 46.87%  β”‚ [] (11791), [{"endTime":"00:01:39.860","na (8), [{"endTime":"00:02:44.246","na (8), [{"endTime":"00:    β”‚
β”‚ 31 β”‚ OpenFunscripter        β”‚ 636    β”‚ 2.25%   β”‚ {} (12), {"bookmarks":[]} (7), {"Bookmarks":[],"Recordings":[ (5), {"Bookmarks":[],"Recordings":[ (5    β”‚
β”‚ 32 β”‚ metadata.average_speed β”‚ 341    β”‚ 1.21%   β”‚ 203 (4), 348.139691075664 (2), 357.76248359314405 (2), 105 (1), 113 (1), 122 (1), 132 (1), 165 (1),     β”‚
β”‚ 33 β”‚ info                   β”‚ 502    β”‚ 1.78%   β”‚ "Automatic generation script f (238), "Created with HandyAlexanders  (234), "Automatic generation sc    β”‚
β””β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

I am the popular scripter software
All scripts on the site pass through my hands (when downloaded)
(as I’ll have to add tags/title/topicUrl/scripter anyways)

(so feel free to suggest any backwards compatible changes, anyone who downloads a script will start getting 2.0 transformed script after RFC is finished)

Ok, so it is renaming the video too and this is on the enduser not the player?

This site is not the only source of scripts and its not guaranteed to exist in the future. The scripting software will still be floating around though.

3 Likes

Yes, the .max option renames the merged funscripts on eroscripts, but you also have to rename the video or you have to configure the script player to load .max.

I am the developer of Restim, which is popular e-stim control software that uses funscripts as input. My software uses many different funscripts, xxx.alpha.funscript, xxx.beta.funscript, xxx.volume.funscript, xxx.pulse_frequency.funscript, xxx.rise_time.funscript, etc. These function similarly to funscripts for multi-axis strokers.

One thing I value is compatibility with existing software. OpenFunScripter is the most popular scripting software and MultiFunPlayer is something I used a lot early in development. This is why I choose to use separate funscripts. At some point I realized that haggling so many funscripts was annoying, so I implemented loading funscripts from folder or zip file with the same name as the video.

Using this method, one can preserve compatibility with older scripting software.

Myself and several of my users also have been working on post-processing scripts. Here you take some funscripts (i.e. normal stroker funscript, or alpha+beta+pulse_frequency) and generate the other scripts using some mathematical formula. These processing scripts are a bit easier to create with separated funscripts.

Given the way estim development has been going, I foresee a future where scripters not only need to distribute funscripts, but also a small configuration file. Here are various use cases:

  • in my software the axis range for pulse frequency is not standardized, some users prefer 0-100 and others 0-200. But some files are specifically made for certain ranges. I believe scripters would like the ability to suggest specific default range per axis for the file. Some axis start at nonzero (alpha has valid range 0-1 and rise time 2-20 on current hardware).
  • I believe users would like the ability to customize the axis ranges on a per-video basis rather than global.
  • Some hardware may work better with specific ranges than others, and some hardware may require a different set of funscripts. It would be nice if scripters could distribute a set of non-duplicated funscripts and a small configuration file. If hardware is X, use these funscripts. If hardware is Y, use those funscripts.

My proposal:

  • Keep .funscript as a dumb, single-axis container 0-100.
  • Absolutely do not use L0, L1, R0 as keys. Use human readable names, sway/twist/roll/alpha/… as recommended by others.
  • For multi-axis devices, distribute separate files or a .zip. Users that wish to use legacy software such as OFS can simply unzip the files.
  • Improve funscript loading logic to load all files in a zip or folder with the same name as the video, the funscripts themselves don’t have to match. This so that users don’t have to rename 10 funscripts.
  • If we wish to add any of the future functionality such as custom axis limits, this can easily be done by adding an application-specific configuration file to the zip/folder. The main advantage is that scripters/users only have to edit one short file with simple syntax instead of 1 massive funscript file or 10 separate funscript files.

I don’t see .max becoming a success as long as OFS doesn’t support it, which it won’t.

4 Likes

This is explicitly not considered as otherwise we’ll get stuck with whatever was user 3 years ago. That’s why I’m trying to invent something great to use in the next three years here.
Making a software to split/merge scripts for use with legacy software is as simple as a software could be.

I will personally patch OFS if it’ll be needed to support the new format.

It’s a fine idea, but specifics are flaky. I haven’t seen it used (ever) much probably for a reason. It’s always either a zip with the video itself or plain scripts.


  • I like the config/ranges option. I want it for SR6 scripts to auto-downscale R12 of my OSR2.
    • What values would you use? I think I need target device output range, but for other devices it may differ
  • How would naming for different hardware look like? I too want this but not sure how should that look like yet. Please tell me your thoughts, mine are roll.SR6, SR6.roll, roll[SR6], [SR6].roll and tbh I don’t really like them.
  • .funscript will be backwards-compatible for single-axis devices and there’ll be software to split it. The only reason you prefer zip here is because you have zip archiver installed imo.
  • I’m 90% sure the site won’t allow zip uploads by exact reason they can be unzipped and contain anything (including files not visible in archive)
  • I agree on 10x renaming and editing, but IMO editing a single json file with notepad will always be simpler then a file in a zip, as long as all the data to edit is placed on the top and not randomly in the middle or end (which I plan to enforce)

TBH I’ve found it opposite way, it’s way simpler to take a single file and patch it then having to list all files in a directory and try to group them by name

And if it would? If that’s the only problem, that’s not a problem at all


Thanks for the input, gonna apply some thoughts onto the draft

Config draft

interface Ranges {
  [axis: axis]?: {
    // example: { roll: { device: "SR6", pos: [0, 100], 
    //                    devicePos: [-25, 25], deviceUnit: "deg" } }
    // example: { roll: { device: "SR6", pos: [0, 100], 
    //                    devicePos: [-25, 25], deviceUnit: "deg" } }
    device: "OSR2" | "SR6" | "SSR1-Twist" | "Handy" | "Handy 2 Pro" | "<some vibe device>";
    pos: [number, number]; // e.g. [0, 100] or [2, 20]
    devicePos: [number, number]; // e.g. [-25, 25]
    deviceUnit: "deg" | "L0" | "Hz" | "..."

   // or maybe
   deviceRange: "-25deg 25deg" | "-0.25L0 0.25L0" // css-like
  }
}
interface Funscript {
  ranges?: Ranges;
}

Its a big part of the problem but not the only part. You’ll also need to go to all the parser software and get them to add support. Changing a well established standard is no easy feat.
So now you’ll be forced to maintain two formats for people that do not use software that can parse a new format.
Things will get chaotic quick. Its probably not worth the trouble.

Personally, I’m not messing with any new format unless I see it can bring high value. Nothing I’ve seen proposed in this thread will do that.

Config file is fine if its 100% optional. XTP has its own config. I would say most parsers has their own config. Also the default funscript standard has some config in the header. Not sure a separate file is needed.

4 Likes

I think this is seriously being over thought at this point.
We wanted to add multiple tracks into the funscript.
check
The rest of the discussion was just details about the structures. We figured that out.
check
Nothing else needs to be done. We have the solution both Yoooi and I agreed upon posted here [RFC] Single-file multi-axis - #28 by Khrull

You can extend that how ever you want but the core functionality of the format is good.

2 Likes

I feel like this may be relevant

2 Likes