Skip to content
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

Closed
Zalunda opened this issue Jul 4, 2022 · 11 comments
Closed

Add support for chapters and bookmarks #72

Zalunda opened this issue Jul 4, 2022 · 11 comments
Assignees
Labels
enhancement New feature or request major-task Enhacement or bug that requires major code changes
Milestone

Comments

@Zalunda
Copy link

Zalunda commented Jul 4, 2022

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.

@Zalunda Zalunda added the enhancement New feature or request label Jul 4, 2022
@Yoooi0
Copy link
Owner

Yoooi0 commented Jul 4, 2022

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.
I would probably support both bookmarks and chapters, with end goal of having a preview of all chapters/bookmarks akin to the heatmap, where you can press on them to seek the video, but not sure how usable would that be due to watching videos in vr.

Action ideas:

  • SeekToBookmark (by index/name)
  • SeekToChapter [Start, End] (by index/name)
  • SeekTo [Next, Previous] [Bookmark, Chapter]
  • AddBookmark
  • [Start, End] Chapter

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).

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...😉

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.
You can probably get pretty much the same functionality by recording all the time with audacity or other software and referencing bookmark by index/time/name.

@Yoooi0 Yoooi0 changed the title Add an action that save the current timestamp in a file Add support for chapters and bookmarks Jul 4, 2022
@Yoooi0 Yoooi0 added this to the 1.x milestone Jul 4, 2022
@Zalunda
Copy link
Author

Zalunda commented Jul 5, 2022

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 =
1.0000), instead of timestamps. This is looking for trouble IMO. If you have a video that doesn't have exactly the same duration as someone else, the chapter/bookmark would all be messed up, and fixing it by hand would be a pain in the butt, especially if you don't know the exact duration of the original file.

{
	"HandyControl": {
		"version": "1.1.0",
		"chapters": [
			{
				"GUID": "bbd3a400-cba0-4e6c-8475-1e12e11bd180",
				"name": "Intro",
				"description": "",
				"start": 0.007819372,
				"end": 0.03384824,
				"bookmark": 0,
				"root": false,
				"chapters": []
			},
			...

Instead of something like:

				"start": "00:00:00.323",
				"end": "00:04:36.221",

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.
Does a MultiFunPlayer have a way to "control" the "VR player" (ex. DAO)? I never looked at the protocol but I always thought that the communication was one-way: The video player sends its current position all the time and the "script player" use that to control the device. Nothing more.

@Yoooi0
Copy link
Owner

Yoooi0 commented Jul 5, 2022

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.

I see 3 possible solutions:

  1. Embedded chapters/bookmarks in funscript
  • Pros:
    • Can work with script streaming if scripting software would include them
    • Less files for users to handle
    • No problems with mapping video -> chapters
  • Cons:
    • Can work with script streaming but read only
    • Chapters/bookmarks would be funscript specific and if there is another script format in the future all saved chapters/bookmarks would be unusable (but maybe thats fine?)
    • Have to modify original funscript to add chapters/bookmarks from MFP
  1. Separate file per video
  • Pros:
    • Not tied to specific script format or application
    • Does not touch original funscript
    • No problems with mapping video -> chapters if stored next to script/video
  • Cons:
    • More files
    • Have to somehow handle script streaming/no "physical" script file on disk
  1. Save chapters/bookmarks to MFP settings
  • Pros:
    • Not tied to script format
    • Supports script streaming via video path -> chapters map
  • Cons:
    • Internal to MFP
    • Have to have a map of video path -> chapters which can break when renaming/moving video files

Cant really decide between option 1. and 2.
3. is meh because OFS would be able to export that.

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 = 1.0000), instead of timestamps. This is looking for trouble IMO. If you have a video that doesn't have exactly the same duration as someone else, the chapter/bookmark would all be messed up, and fixing it by hand would be a pain in the butt, especially if you don't know the exact duration of the original file.

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.

Yea I think start/end should be milliseconds from start, or in hh:mm:ss:fff format.
Dont see the use of a ID/GUID field, the id could just be an index in the chapter list.
Also nested chapters are overkill imo.
So it would be just:

{
  "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.

Outside the subject a little bit but I'm kind of curious about the SeekToBookmark.
Does a MultiFunPlayer have a way to "control" the "VR player" (ex. DAO)? I never looked at the protocol but I always thought that the communication was one-way: The video player sends its current position all the time and the "script player" use that to control the device. Nothing more.

Yes, currently you can seek and play/pause from MFP. Adding loading of files should be easy.
Whirligig is the only one to not support remote control afaik.

@Zalunda
Copy link
Author

Zalunda commented Jul 6, 2022

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).
It should also include more than just the chapters. It would track location, men's position, type of actions, and, maybe, women's position (I'm not certain it's useful since it's often related to the type of actions).

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.
For example, "menPosition" is "Standing" from "00:00:00.000" to "00:05:43.000" because it isn't modified in section "B".
With this information available, we could make a really detailed heatmap/scene description with men/women positions, action, etc.

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.
The "transforms" could modify the script for all sections, or only sections that match some filter. I think this could work very well with all the transformation that MFP support (ex. attach L0-to-V0 but only for blowjob section)
The "bookmarks" is the parts that MFP could update (i.e. the initial subject of this feature request 😉).

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"]
	},
	...
}

@Yoooi0
Copy link
Owner

Yoooi0 commented Jul 6, 2022

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.

True, but what if we do both. (inserts why not both.gif)
So for example scripters/OFS would save that data to the funscript:

{
  "actions": [],
  "rawActions": [],
  "metadata": {
    "chapters": [],
    "bookmarks": [],
    "actors": [],
    "creator": "",
    ... other scene/script metadata ...
  }
}

But we also support loading the same metadata from a separate file like <video name>.funscript.meta:

{
  "chapters": [],
  "bookmarks": [],
  "actors": [],
  "creator": "",
  ... other scene/script metadata ...
}

This way we have best of both worlds. MFP would save to that separate .meta file.
But this would probably need to be discussed with OFS too.

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.

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, the way I see it, we should have 3 layers/files.

So first file would be the metadata which like I said could be either in the funscript itself or in separate file.
Tho I think chapters should have start and an end, otherwise you cant have gaps between chapters.
Other stuff could be put into chapter metadata:

{
  "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 startTime, endTime, name are required, everything in metadata would be optional.
You cant be too clever with the format or it will be a pain to implement, it needs to be simple data storage without requiring any logic.

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.

@Yoooi0 Yoooi0 added the major-task Enhacement or bug that requires major code changes label Oct 22, 2022
@OpenFunscripter
Copy link

OpenFunscripter commented Nov 9, 2022

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).

Since mpv supports Lua scripting I feel like you could implement this using a Lua script + some command line tool which records audio. 🤔
I don't know if this is actually possible (not that familiar with mpv Lua scripting) but it sounds possible.

On the topic of bookmarks.
I've been asked for multiple times over the past 2 years to add an export and too me it's always been fairly irritating.
Because I always felt like it was out of scope for OFS.
I also never understood why people would want to spend so much time on creating these elaborate bookmark/chapter files. But I guess given that funscript creation itself is already so time consuming it doesn't matter. 🤷‍♂️

{
  "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.
I'm willing to add this to OFS. The bookmark "system" requires an overhaul anyway.
However many things in OFS require an overhaul at the moment.
So it would be very low priority for me

@Zalunda
Copy link
Author

Zalunda commented Nov 9, 2022

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:

  1. Start with the high-level definition of the scene.
  2. Decide if I really want to make a script for that scene. For example, if I notice that 50% of the time is spent with the man "in control" (which I don't like), I'll abandon the script right there. I'll already do that but, sometimes, I only notice while scripting.
  3. Have visual cues for each section in OFS while working (right now, I'm using bookmarks to mark the start of each section):
    image
    Bonus request for OFS: It would be nice if we could "select" a section and limit all the actions inside that section. For example, selecting all points to the right of the cursor would only select the points inside the current section. I often use that feature to move all points after using Motion AI, but I can't if I already scripted other sections later in the video.
  4. While testing my script in VR, be able to save bookmarks in a format that OFS could automatically import.
  5. ... finish the script.
  6. [Plug for my own tool] Use FunscriptToolbox to add an audio signature in the .funscript and, in the future, generate a detailed heatmap that uses the high-level definition.
  7. Publish the script, maybe with "transformation" files. For example, "RemoveMenActions.transform" could be applied to the script to remove some parts of the original script. It might just be me but I don't like having multiple .funscript floating around, especially if I need to make modifications later on.
  8. If people have comments to make about specific parts of my script, they can save the bookmarks while in VR and link the bookmark file to their comments. Which I could reload in OFS to adjust if needed.

@Yoooi0
Copy link
Owner

Yoooi0 commented Nov 10, 2022

Because I always felt like it was out of scope for OFS.

Given that OFS already has some metadata fields I dont think it is entirely out of scope.
Its kinda like adding chapters in a video editor.

Its just low priority because we dont know if it will catch on.
From MFP side I can think of few cool features if this gets added on both sides, like:

  • Skip current chapter if you dont like the position with a shortcut without having to seek thru the video
  • Auto skip to a preferred chapter name on video load, for example if it is named "blowjob" or whatever
  • AB loop a chapter, AB loop between bookmarks

And probably other cool stuff.

This is very detailed but I thinks it's what the people want.
I'm willing to add this to OFS. The bookmark "system" requires an overhaul anyway.
However many things in OFS require an overhaul at the moment.
So it would be very low priority for me

Yea I don't think I would add this without OFS supporting it.
If we can agree on the format then at least that would be one step forward.

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": ""
}

startTime, name would be required.
endTime would be optional, if not provided the endTime would equal startTime of next chapter.

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.
We could leave chapter/bookmark metadata for future addition, or have it as a simple string key-value pair but without standardized field names there might not be a point.

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"
}

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.

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.
I think simple chapters and bookmarks would be a good start with main groundwork done.

Publish the script, maybe with "transformation" files. For example, "RemoveMenActions.transform" could be applied to the script to remove some parts of the original script. It might just be me but I don't like having multiple .funscript floating around, especially if I need to make modifications later on.

Yea that will definitely be out of scope of both MFP and OFS, better suited for separate app.

@OpenFunscripter
Copy link

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.
I think simple chapters and bookmarks would be a good start with main groundwork done.

True.
The simple version is a good starting point.
I prefer the version where bookmarks and chapters are separate.
The coloring is something I would implement but not export to the .funscript.

Anyway I don't want to further intrude in your repository with my stuff.

@Yoooi0
Copy link
Owner

Yoooi0 commented Nov 10, 2022

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.
We can further discuss the json/implementation in OFS issue when/if you make one.

@Yoooi0
Copy link
Owner

Yoooi0 commented Dec 11, 2022

@Zalunda

Added first revision of chapters and bookmarks to MFP with seek by name/index/prev/next actions:
2022-12-11_23-56-48
Build: https://github.com/Yoooi0/MultiFunPlayer/actions/runs/3671197972

They will probably be read only for now since there is also a OFS media source which live updates scripts from OFS to MFP.
Ability to create chapters/bookmarks from MFP will probably be in separate issue if/when someone makes one.

I'm not 100% happy with the display so any suggestions are welcome.
You should probably also make suggestions in OpenFunscripter/OFS#55 about the OFS side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request major-task Enhacement or bug that requires major code changes
Projects
None yet
Development

No branches or pull requests

3 participants