XTPlayer - Cross platform TCode sync (OSR, SR6) Stream your local media and sync funscripts to almost any device with a browser

Ya i said a while back, I have not seen any in the wild on EroScripts or otherwise.
One thing stopping me is I need to see the format. I’ve not seen any files and I don’t know if the standard is documented anywhere.
A single file it would make script discovery much easier I think but I don’t want to work on something that’s not a thing really.

I assume you’re talking about site-wide on ero-scripts right?

1 Like

30% of poll voters seem to want single-file multi-axis

As seen in my https://discuss.eroscripts.com/t/shaggysusu-citlali-animation-genshin-impact/240301 it works fine for folks with MFP

You may find less biased numbers in link counters of recent Falafel’s posts


Implementation details: scripts may have both actions and L0 axis, in this case actions should be threated as a script variant for wingless is devices
So as you don’t support Handy and other single-axis devises just always prefer L0 axis over root actions

Took a look and here are my thoughts

  • Why are there two different formats? This will just muddy the water. There’s no need for it. Make single format and stick with it. This makes it easier on everyone.
    I’d suggest going with strok channel being the same format as a standard funscript. Then add the other channels as sub objects like similar to one of the scripts in that post.
  • Also axes should be called channels because as not all channels are on an axis. We also have vibe, suck, lube etc. Axis is a dimension in space.
  • I don’t think the channel ID should be in there at all. Give it a standard name like the names we currently use. twist, sway surge as that says what they are better than L1, L2 and so forth. L1 and L2 may not always be tied to sway and surge but sway will ALWAYS be sway etc. L1 and L2 are TCode commands specifically. Why tie the format to TCode? Its a funscript and should not know anything about tcode.

I don’t think this format was thought out very well.

I didn’t invent this format, I’ve just found it’s support in MFP

And MFP apparently supports it because SLR sends multiaxis scripts in this format?

@Yoooi could you tell the history of it?

Yes I know the history and I never really liked it. Its partially the reason why i didn’t mess with it. The other part is its tied to a proprietary system and I didnt see it going anywhere only being a few paid multi funscripts from SLR.
If the community takes it over, I think we should do it better.

I roughly agree with this with some nitpicks

  • There is no definition of Funscript, there are only implementations. I’m slowly planning out the schema (I’ll invite you and anyone in the space to a thread later), and all funscripts will be converted to it when trying to download
  • TCode spec strictly defines L0-L2 and R0-R2 (and maybe A0-A2 idk). Other axes go to [LRAV][3-9] space.
  • Naming it axes is fine cuz if you forget about rarely used A, L and R are divinely axes.
  • I agree alternative to axis.id would be good, but for 0.2 of my lib removed it for id for simplicity
  • I think some device parameter somewhere would be useful - for handy/SSR1, OSR2/SR6, OSR/Twist variants of same axis
  • L0 actions being on root vs axis - I also think root actions will be the default, I just want to have a defined behaviour when both are present

There is no definition of Funscript, there are only implementations. I’m slowly planning out the schema (I’ll invite you and anyone in the space to a thread later), and all funscripts will be converted to it when trying to download

The funscript standard is outlined:

TCode spec strictly defines L0-L2 and R0-R2 (and maybe A0-A2 idk). Other axes go to [LRAV][3-9] space.

Funscript has nothing to do with TCode. nor vice versa. Technically a multi funscript could be used on ANY multi channel protocol and it shouldnt be linked to TCode in any way as they are two different things. Our funscript to TCode players are meant to map the funscript actions TO tcode. Its why they exist in the first place. Because they are different entities and have nothing to do with each other.

Naming it axes is fine cuz if you forget about rarely used A, L and R are divinely axes.
I agree alternative to axis.id would be good, but for 0.2 of my lib removed it for id for simplicity
I think some device parameter somewhere would be useful - for handy/SSR1, OSR2/SR6, OSR/Twist variants of same axis

But they are NOT axis so it doesn’t make sense to call them that. Just because they aren’t used much now doesn’t mean the wont in the future. Channel is a much better avenue as it is flexible enough to mean any sort of mod/addon and not just coordinates of space.

L0 actions being on root vs axis - I also think root actions will be the default, I just want to have a defined behaviour when both are present

Offering multiple paths to the same destination just causes confusion in all parties. Now some scripts will be compatible with some players and how to tell the difference when they all look the same from the outside. So devs need to add multiple paths to handle ALL possible configurations increasing dev complexity and time working. Its a bad idea and I will not be supporting it.

2 Likes

Thanks for the link

I think I will make 1.0 schema based on this Go implementation,
2.0 schema based on the OFS implementation (or whatever OFS sets to version field)
And 3.0 schema for multiaxis implementation with deprecating features no-one uses (<< 1% usage in 27k Scripts > Free Scripts )
(Because I doubt most implementations care about Inverted and Range)
(Support table may be a great thing to make later)

But those in go version are not a problem

One of my main problems is metadata.duration, which is very often 0, generally rounded seconds (which I don’t like as that’s not precise enough for len-0-2 scripts ), sometimes milliseconds (wut)
I will write a used feature table later this week (it’s currently half-baked counting scripts but I do have some of the numbers)

Ya the metadata has been mostly useless to me. I figured the launch used it or something. I dont normally look at the scripts contents personally.

Hi guys, I bought some DRV8833 controllers to upgrade the SR6 (with ESP32) with vibration motors (did not arrive yet, currently thinking about the best way to mount them inside the FL case, probably in thick silicon tubes and zip ties through drilled holes, other tips appreciated…), the lube pump is currently connected directly to power bus and operated with a button. I would like to connect it via the DRV8333 too, is it possible to wire it up so that the button can remain operable? Or did anyone try to control it via gamepad remote with Khrull’s software? Only have PS5 controller, dunno if that could be used… Sorry to ask it here, feel free to direct me to a more suitable topic. Thanks

Im not sure if PS5 gamepad can be used or not. Heres a link to the docs for the library I use.

It only mentions XInput on windows but looks like PS5 uses DirectInput. Best way to find out is try it I suppose. If not there may be a way to trick it to thinking its XInput as lots of games use XInput.

You should be able to use V1 and V2 channels to control the speed of the vibrations using the PWM on that driver from a pin on the ESP32.

You probably have plenty of pins available so using the lube button and 2 drivers shouldn’t be an issue.

SO I noticed this.

The very fact the names are here next to the ID should tell you that the TCODE channel as the ID is a bad idea.

If the ID was the name then it can be simplified. Again TCODE is NOT Funscript and they should be kept separate for compatibility with non TCode devices that are multi axis.

There could be a day when a multi axis device is invented that doesnt use TCode. Then we are stuck with these terrible IDs…

New version v0.5b just released. https://www.patreon.com/posts/131917355

1 Like

great update. speed control is awesome! seem to be crashing when i go fullscreen with the video tab open in an external window

Got all excited, but .5b crashes on launch. Log attached to see if it helps. I’m assuming it’s the older MacOS version that you mention in the release notes, but can’t confirm. Running M2 Max.

Process: XTPlayer [41919]
Path: /Applications/XTPlayer.app/Contents/MacOS/XTPlayer
Identifier: com.yourcompany.XTPlayer
Version: ???
Code Type: X86-64 (Translated)
Parent Process: launchd [1]
User ID: 501

Date/Time: 2025-06-22 21:28:44.1756 -0600
OS Version: macOS 14.7.6 (23H626)
Report Version: 12

Time Awake Since Boot: 41000 seconds

System Integrity Protection: enabled

Notes:
PC register does not match crashing frame (0x0 vs 0x109B44B5E)

Crashed Thread: 0 Dispatch queue: com.apple.main-thread

Exception Type: EXC_BAD_ACCESS (SIGBUS)
Exception Codes: KERN_PROTECTION_FAILURE at 0x0000001400003000
Exception Codes: 0x0000000000000002, 0x0000001400003000

Termination Reason: Namespace SIGNAL, Code 10 Bus error: 10
Terminating Process: exc handler [41919]

VM Region Info: 0x1400003000 is in 0x1000000000-0x7000000000; bytes after start: 17179881472 bytes before end: 395136978943
REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL
commpage (reserved) fc0000000-1000000000 [ 1.0G] —/— SM=NUL reserved VM address space (unallocated)
—> GPU Carveout (reserved) 1000000000-7000000000 [384.0G] —/— SM=NUL reserved VM address space (unallocated)
GAP OF 0x5f9000000000 BYTES
MALLOC_NANO 600000000000-600020000000 [512.0M] rw-/rwx SM=PRV

Error Formulating Crash Report:
PC register does not match crashing frame (0x0 vs 0x109B44B5E)

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libxtengine.1.0.0.dylib 0x109b44b5e LibraryListItem27::LibraryListItem27(LibraryListItem27 const&) + 158
1 libxtengine.1.0.0.dylib 0x109b49bca QtPrivate::QCallableObject<HttpHandler::HttpHandler(MediaLibraryHandler*, QObject*)::$_9, QtPrivate::List<int, QList>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) + 186
2 QtCore 0x10e35cdee QObject::event(QEvent*) + 670
3 QtWidgets 0x10af389f4 QApplicationPrivate::notify_helper(QObject*, QEvent*) + 308
4 QtWidgets 0x10af399b6 QApplication::notify(QObject*, QEvent*) + 502
5 QtCore 0x10e310183 QCoreApplication::sendEvent(QObject*, QEvent*) + 147
6 QtCore 0x10e31096e QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) + 542
7 libqcocoa.dylib 0x10bd5f51a 0x10bd46000 + 103706
8 libqcocoa.dylib 0x10bd5da59 0x10bd46000 + 96857
9 QtWidgets 0x10b1422d7 QSplashScreen::showMessage(QString const&, int, QColor const&) + 135
10 XTPlayer 0x1008f1b98 MainWindow::MainWindow(XTEngine*, QWidget*) + 29096
11 XTPlayer 0x1008e411b main + 25419
12 dyld 0x200f7b345 start + 1909

Looks like youre running MacOS 14. I built this package in MacOS Sequoia 15. It may be due to that. I mentioned this in the release notes.
I need to get a build setup with an older system at somepoint.

Edit: Oh I see you mentioned this…my bad. Ya I cant tell anything from that report specifically. Ill get an older build setup and re release it. I can DM it to you beforehand if you want?

Hmm, thanks! What OS?
Edit: Nvm, just made it happen on my main build machine. Looking into it.
Edit: yup NRE Oversight and an easy fix. I may try to get an older mac build before I release another build though.

It just closes after “Starting application” in initial logo window with new update

prev version work flawlessly

win10 if it’s matter

Thanks, but it’s okay, don’t go out of your way. Might be the motivator I need to finally update to 15 :slight_smile: I’ll keep an eye on this thread/github if you do release an older one though.

Been trying all morning. Apple doesn’t make it easy that’s for sure. Partly because I dont know MacOS that well but ugh…