New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for chapters and bookmarks #72
Comments
So I was thinking about adding support for chapters like these, but I dont know if people even use those, or if OFS supports them, need to research. Preferably would support something generated by OFS to not make a new custom format, and so the scripters can provide them easier. If they are not compatible or they are not popular id rather save all bookmarks to the main settings file, with possible export options. I dont really want to touch files outside MFP folder. Action ideas:
Might be also nice to auto load a file when user wants to jump to some bookmark, that would require some sort of bookmark manager (self note: this would have to somehow work with auto skip to script start functionality).
This is just a player not a scripter so it would need to make sense to that use case, so that is way out of scope, and would probably require a lot of code. So low chance of something like that happening. |
Unfortunately, from what I understand, OFS doesn't support any bookmarks import or export so far (ref: https://discuss.eroscripts.com/t/how-can-i-export-bookmarks-timestamps/60018). So, there isn't a format to be used there. I understand about not wanting to modify files that MultiFunPlayer doesn't "own". Personally, I wouldn't mind as long as MultiFunPlayer never deletes information (i.e. it only adds bookmarks/chapters at the end of an existing file). But it would also be OK if the bookmarks are saved in one of MultiFunPlayer's folders, preferably one simple file per video, without having to extract anything. Using the chapter format is a good idea but, looking at it, there are parts of the file format that I don't really like (besides the fact if it's named .hc and the first JSON node is 'HandyControl' 😉). For example, the "start" and "end" properties seem to be a fraction of the whole file (start => 0.0000, end =
Instead of something like:
As a 'standard format', I'm not sure about the GUID property as well. It could be replaced with 'ID' and an application could put a GUID if it wants, but a user making the file by hand could use any unique string. And last, for the Audio part, I understand the complexity and I'm not even sure that it's really needed. If I'm able to easily put bookmark exactly where a see/feel a 'script problem', and analyze it in OFS afterward, I'll probably remember what was wrong without audio comments. Outside the subject a little bit but I'm kind of curious about the SeekToBookmark. |
I see 3 possible solutions:
Cant really decide between option 1. and 2.
Yea I think {
"startTime": "00:00:00.323",
"endTime": "00:04:36.221",
"name": ""
"description": ""
} For chapters, and: {
"time": "00:00:00.323",
"name": ""
"description": ""
} for bookmarks. Not even sure it needs to be in json, csv would be just fine.
Yes, currently you can seek and play/pause from MFP. Adding loading of files should be easy. |
Short answer, my choice would definitely be 2. It could be useful to be able to create and share a chapter/bookmark file for a paid-funscript (for example, a script from realcumber). If everything is in the same file, we wouldn't be able to do that. Now, prepare yourself for the long answer... 😁 This is something that I thought about for a while now since I want to make a "FunscriptToolBox" at some point. A tool a bit like ffmpeg with a lot of useful functions related to funscript, without being a "scriptplayer" or "scriptmaker". For example, extract or merge video and funscript parts at the same time, create detailed heatmap, etc. A bit like funscript.io but that can work with a command line or UI. So, the way I see it, we should have 3 layers/files. The first file should be the "scene definition". It describes the scene by itself. In some way, this is a file that could ultimately be released by the studio itself. I should have the basic information on the scenes (studio, scene name, actress, release date, actor, duration). Something like this: {
"studio": "CosplayVR",
"sceneName": "Sucker Punch: Blondie",
"Actresses": ["April Olsen"],
...
"sections": [
{
"name": "A",
"startTime": "00:00:00.000",
"chapter": "Introduction",
"location": "Outside",
"menPosition": "Standing",
"womenPosition": "Standing",
"action": "Talking"
},
{
"name": "B",
"startTime": "00:04:36.221",
"action": "HandJob"
},
{
"name": "C",
"startTime": "00:05:43.000",
"chapter": "Inside the house"
"location": "Living Room",
"menPosition": "Sitting",
"womenPosition": "Kneeling",
"action": ["Blowjob", "Handjob", "Tits fucking"]
},
{
"name": "D",
"startTime": "00:08:34.134",
"womenPosition": "Sitting??",
"action": "Cowgirl",
},
{
"name": "E",
"startTime": "00:10:16.000",
"action": "Reverse Cowgirl",
},
{
"name": "F",
"startTime": "00:12:27.268",
"menPosition": "Standing",
"womenPosition": "Doggy",
"action": "Doggy"
},
{
"name": "G",
"startTime": "00:16:35.268",
"location": "Bed Room",
"menPosition": "Lie Down",
"womenPosition": "Sitting??",
"action": "Cowgirl"
},
...
{
"name": "N",
"startTime": "00:33:35.268",
"endTime": "00:36:17.234"
"action": [ "Blowjob", "Cum in mouth" ]
}
]
}
For each "type" of tracking, the endTime is calculated automatically when another section overrides the value. The second file is the funscript itself, like it is right now. The third file could reference the scene and funscript definition to tailor the experience according to the user's preference. Something like this: {
"playlist": [ "A", "B", "B", "C", "D", "N" ],
"transforms": [
{
"type": "SpeedLimiter",
"speed": "400" [in unit per sec] (or something like "Handy" that has a pre-determined speed )
"applyto": "all"
},
{
"type": "MinimumIntervalBetweenPoints",
"speed": "50" [in ms] (or something like "Handy" )
"applyto": "all"
},
{
"type": "FillGap",
"minGapDuration": 30000 [in ms]
"minPos": 20,
"maxPos": 80,
"duration": 1000 [in ms],
"applyto": "all"
},
{
"type": "IncreaseIntensity",
"amount": "20%"
"applyto": ["action=Blowjob"]
},
{
"type": "DecreaseIntensity",
"amount": "10%"
"applyto": ["name=B", "name=N"]
},
{
"type": "IncreaseIntensityFull",
"applyto": ["action=Cowgirl"]
}
],
"bookmarks": [
{
"time": "00:18:35.268",
"name": "",
"description": "noticable relocation"
},
{
"time": "00:23:35.268",
"name": "",
"description": "too intense"
},
{
"time": "00:28:35.268",
"name": "",
"description": "not intense enough"
},
{
"time": "00:29:18.268",
"name": "",
"description": "not intense enough"
},
]
} The "playlist" could allow the user to skip sections that they don't like, or replay multiple times the same section. Ideally, the user should also have a "global-preference" file that would apply to all his scripts. Something like this: {
alwaysSkips=["action=Doggy"],
"transforms": [
{
"type": "SpeedLimiter",
"speed": "Handy"
"applyto": "all"
},
{
"type": "MinimumDelayBetweenPoint",
"speed": "Handy"
"applyto": "all"
},
{
"type": "IncreaseIntensity",
"amount": "10%"
"applyto": ["scripter=Zalunda"]
},
{
"type": "DecreaseIntensity",
"amount": "20%"
"applyto": ["scripter=TooIntenseScripter"]
},
...
} |
True, but what if we do both. (inserts why not both.gif) {
"actions": [],
"rawActions": [],
"metadata": {
"chapters": [],
"bookmarks": [],
"actors": [],
"creator": "",
... other scene/script metadata ...
}
} But we also support loading the same metadata from a separate file like {
"chapters": [],
"bookmarks": [],
"actors": [],
"creator": "",
... other scene/script metadata ...
} This way we have best of both worlds. MFP would save to that separate .meta file.
Hah, yea I wanted to make an easy way to cut videos with scripts too. Currently waiting on losslesscut to add plugin/api support, but might do it myself eventually.
So first file would be the metadata which like I said could be either in the funscript itself or in separate file. {
"startTime": "00:00:00.323",
"endTime": "00:04:36.221",
"name": ""
"metadata": {
"description": "",
"location": "Living Room",
"menPosition": "Sitting",
"womenPosition": "Kneeling",
"actions": ["Blowjob", "Handjob", "Tits fucking"]
}
} Where The third file is obviously out of scope of this issue but I will just say that it would need to be internal to MFP, coming up with a common format for that would be a pain, and I think json isnt the best way to store such logic, a better solution would be to create a visual programming type of editor in MFP to configure all of this, and then have it export to config files that wouldnt be easily editable. Or even add support for scripts in C#. IMO I dont think there is even a need for such detailed script setups, there would be barely any use of this but a lot of code to add. |
Since mpv supports Lua scripting I feel like you could implement this using a Lua script + some command line tool which records audio. 🤔 On the topic of bookmarks. {
"startTime": "00:00:00.323",
"endTime": "00:04:36.221",
"name": ""
"metadata": {
"description": "",
"location": "Living Room",
"menPosition": "Sitting",
"womenPosition": "Kneeling",
"actions": ["Blowjob", "Handjob", "Tits fucking"]
}
} This is very detailed but I thinks it's what the people want. |
It's interesting to see a cross-application (OFS / MFP) discussion here. :) I'm might not be a typical person, but I love declarative formats that could be expanded in the future, even if it's overkill sometimes. I think that it would be really useful for everyone to have detailed heatmaps for scripts (that include men's and woman's positions, with visual duration). Personally, I would be able to know right away if I'm interested in a scene or not. If you ask me, as a scripter, my ideal workflow would be something like this:
|
Given that OFS already has some metadata fields I dont think it is entirely out of scope. Its just low priority because we dont know if it will catch on.
And probably other cool stuff.
Yea I don't think I would add this without OFS supporting it. Ideally I think we would have something like this: {
"actions": [],
"metadata": {
"creator": "",
"performers": [],
"license": "",
... other script metadata ...
"chapters": [],
"bookmarks": [],
"OpenFunscripter": {
... OFS specific metadata ...
},
}
} Where chapters would be: {
"startTime": "00:00:00.323",
"endTime": "00:04:36.221",
"name": ""
}
And where bookmarks would be: {
"time": "00:00:00.323",
"name": ""
} Basically to differentiate chapters as a time span, and bookmarks as points in time. Or we could combine them into one object: {
"startTime": "00:00:00.323",
"endTime": "00:04:36.221",
"name": ""
"type": "chapter"
} {
"startTime": "00:00:00.323",
"name": ""
"type": "bookmark"
}
The json/metadata itself is not a problem, but UI for entering/displaying/validating all of this will be a lot of work compared to the amount of people that will fill all of those fields.
Yea that will definitely be out of scope of both MFP and OFS, better suited for separate app. |
True. Anyway I don't want to further intrude in your repository with my stuff. |
Nah not a problem, MFP pretty much depends on OFS implementing this anyways. |
Added first revision of chapters and bookmarks to MFP with seek by name/index/prev/next actions: They will probably be read only for now since there is also a OFS media source which live updates scripts from OFS to MFP. I'm not 100% happy with the display so any suggestions are welcome. |
When doing QA on a script (my own or others), it would be nice if I could use a trigger to save the current timestamp in a "bookmark" file (action: SaveBookmark).
It would be even more useful if MultiFunPlayer could listen & record for a few seconds after the trigger is pressed (action: SaveBookmarkWithAudio). I could then say something like "noticeable relocation", and be able to review my comments at the end of a session. Hopefully, with OFS automatically importing the file, but this is another feature request I would have to ask in the future...😉
A bookmark file could also become a good way to give specific comments to other scripters.
The text was updated successfully, but these errors were encountered: