So, my conclusion is:
When there’ll be a better SFMA format spec, implemented in both MFP and XTP, we may set it as default
And for now we’ll just use the described spec for SFMA (it’s live and on by default), with .funscript extension (with options to use .max.funscript and click-to-download-multiple-files)
Just want to verify. I’m attaching a mockup of the proposed format. This is what it will look like?
video name.funscript (1.3 KB)
Roughly yes, but specifics need some thought
The main problems I see:
- L0/L1/L2 have mismatching scale
- R1/R2 have mismatching scale, and have different scale on different devices
- R1/R2 on devices without L1/L2 may need to be different from R1/R2 on devices with L1/L2
- R0 has different scale on different devices and can actually go to infinity
I think it may be solved with:
- using
deginstead ofposfor R0/R1/R2 - using
offinstead ofposfor L0/L1, which scales with L0 - having multiple axes for R0/R1 for different devices, so a
device: OSR2tag in axis, and multiple axes with same name
None of those have been a problem for now so this is just over complication.
The format should be literally just a copy of multiple files into one file.
I think the objects in the channels should be treated as full funscripts, meaning they could also have its own metadata/chapters/bookmarks etc.
Since you are merging to one file it should just be a direct copy of the files.
It might be better to use a dictionary to prevent duplicate id, and also the funscript objects won’t contain additional id property:
{
"metadata": {...},
"actions": [...],
"channels": {
"xxx": {
"actions": [...]
},
"V3": {
"actions": [...]
},
"twist": {
"actions": [...],
"metadata": {...}
},
"pitch": {
"actions": [...]
}
}
}
Also the channels property kinda sounds like tcode channels, maybe something like additionalActions/extensions?
Well channel can mean any channel. TV, canal, radio. In this case its funscript channels.
tracks also works I think.
We can add what ever we want to any channel/track. I modified my file above to add metadata. The only difference between the root channel/track is it doesnt have an id.
I’m not sure the sub tracks will need any metadata standalone but it can have it in the future if the player wants to parse it.
Technically we dont even need the channels array and just do something like this.
Where all the channels/tracks are root objects. This does make channel look up a bit easier than iterating over an array.
But im fine with the array. I can map it to a dictionary at load and look it up from that. Just food for thought.
Oh ya I see you mentioned a dictionary. Ya duplicates could be an issue. I think I would treat the last one as a win in that case.
A duplicate could happen in a dictionary JSON. Loading it may throw an error but nothing stopping from it being written out in the file.
Track is very common term in video files, like audio track/video track/subtitle track. So maybe that fits better.
Yea, I was just pointing out that for simplicity the objects under channels should be a direct copy of the funscript json and not be limited to only actions.
There is a possibility of a merging multiple already merged funscripts.
In that case I think the channels should be flattened when merging, but I guess this could be also handled in the script players how they see fit.
Until someone tries to merge video.actions.funscript or video.metadata.funscript.
Or if someone specifies that actions should be matched to A3 in TCode players.
This would have to be handled in apps writing or reading merged funscripts.
They should be in a separate property, which is a dictionary. This will IMO simplify reading/writing.
With id you can have multiple objects with id: "twist" which has to be handled, with dictionary its technically possible to edit the json manually but I dont think there is a json library that will not throw errors on reading/writing json with duplicate keys.
Yup, looks good to me.
Serialization stops it
I’ve implied that, but not told this directly
tracks: Record<string, {actions, metadata?}> seems fine
Though I’d prefer requiring id or axis property as otherwise you may have to infer them on deserialization (as tracks may be standalone)
And requiring them allows standalone script to have a defined axis
Not entirely sure what you mean. None of the tracks in the above example are required. You can have 1 or none or not have the tracks object at all of course.
I will be checking for the tracks object then check every possible channel XTP supports when the file is being loaded to see which tracks the script has.
The id becomes the object lookup name and easier to check for existence. Otherwise you have to iterate the whole array looking for the track the player supports.
Are you saying this because the JSON library you are using is awkward with its de-serialization?
It makes more sense to make the id a key in a key/value pair because ids are keys. Let system the handle the key instead of hacking around with a bunch of manual validations.
Do you mean that you have to map “twist” key to “R0”?
I think that was the point of separating it away from TCode is that you don’t do any mapping, the heatmap should also not use TCode axis names and just display the actual string key from tracks.
Hmm okay this is implementation dependent
I gonna need to rethink my lib
The core class doesn’t need to support metadata and axes
Funscript 2.0
Valid funscripts have the following format
type axis = 'stroke' | '...';
interface Action {
at: number // 0.-1e9.
pos: number // 0.00-100.00
}
interface Channel {
// sorted by .at
// L/R axes may not have two points with same .at
// other can have two but not more
actions: Action[]
// effective values of pos units, in L0 or deg units
// defaults to 0-100 for L0, +-25 for L12 and +-15 +-25 +-120 for R012(iirc) (so SR6 scale)
// compatible with legacy scripts that had [5, 95] - they should be upscaled lol
// implicitly allows scaling/inverting
range?: [number, number]
}
interface Script extends Channel {
version: "funscript@2.0.0-alpha.1"
metadata?: Partial<Metadata>
// for L0 axis
actions: Action[]
channels?: {
// stroke channel overrides script.actions for multi-axis devices
stroke?: Channel
[axis in axis]?: Channel
}
// proposed:
// chapters: Record<string, Chapter>
}
// all properties optional
interface Metadata {
title: string
duration: number // .000 in seconds
// proposed: durationTime: timeStamp
// sorted by startTime
// may cross over
chapters: Chapter[]
// auto inferredfrom topic tags
tags: string[]
// auto inferred from topic
author: string
// official link to sauce (not to reuploads)
videoSourceUrl: string
}
type timeStamp = string // "hh:mm:ss.uuu"
interface Chapter {
startTime: timeStamp
endTime: timeStamp
name: string
// proposed to replace with:
// startAt: number
// endAt: number
}
Intermediate script format has following differences:
- allows negative
at atprecision at least .2fatallows UTC numbers (for recordings)posmay be out of 0-100 range
Why so much over complication. The idea was simple, take multiple funscripts and literally ctrl-c, ctrl-v them into one file.
Making so many changes is pointless because it all depends on the scripter software, everyone uses OFS which is not getting updates so the only hope is to make a new OFS first.
I think “funscript2” should also allow bezier moves. I suggested this a long time ago and made a OFS branch for it:
Funscript updates need to be backward compatible, adding a property for bezier or for tracks is backwards compatible, changing behavior/format of everything is not.
Why would you need negative at.
Why, just subtract recording start from each action and convert to ms.
How can you make device move negative % or more than 100%.
Also no device reports the offset/angle range for L1/L2/R0/R1/R2 so I dont know how do you want the script players to translate range to commands which are only 0%-100%.
Ya funscript is a relatively simple format. Lets keep it that way. 0-100 is relative and doesnt know where its going. It just a percentage of two extremes. This way funscript is dumb and simple. The way it should be for the highest compatibility across systems.
I cant see a need for it to be more precise than 0-100. Our bodies arent this sensitive. I’ve never thought to my self, 'If the machine only had a 1/10 offset from the final location it would have been perfect"
If this was a new format Id say sure, why not but we are trying to keep backwards compatibility and I just don’t think the value added is worth it to change much.
Quick question, Can I get a definition of .max.funscript. Ive seen .max.funscripts in the wild and they do NOT have any multi axis tracks in them so I think there maybe some confusion here.
I also see plus.funscript sometimes.
I would rather not have a special extension. This is another path I have to look for files. This is backwards compatible so we can simply use .funscript and let the parser handle the rest.
The old standard .<track>.funscript is already chaotic enough.
Intermediate scripts are for editing not playing you may ignore them
OSR2 range with SR6 [-15⁰, 15⁰] preset is around -150, 250 idk
Has to be user provided cuz yep SR6 and OSR may look exactly same
Weeeell, there’s 360deg R0. Otherwise yep.
Its SLR, I just made settings to use .max prefix
.max should be in the SLR format from first post.
I agree that there should not be any extensions, there can be an option on eroscripts if users want to add an extension and configure the script player, but by default they should just merge `.funscript. This way it is also backwards compatible with older players and does not require configuration changes.
As a bystander just watching this progress, all I think is its way more complicated than it should be. I always thought it would be way more simple if funscripts (especially multi axis) resided in a zip/rar file and Khrull alluded that this was already built in to mfp (and earlier xtp) tho I havent tested the functionality of it yet. The only downside to that, at least for me, is I generally rename the video/funscripts to a format I prefer ie: studio - performer - title, so to have to rename files inside a zip/rar would kinda be a hassle.
@Yoooi I am wondering if I have to do anything special with MFP to utilize these merged scripts? I wasnt sure if they worked automatically or not. I still just dl the separate files like usual.


