GoblinScript - goblin assisted funscript drafting

auto-crop needs more work it does seem to be very hit or miss. perhaps auto-crop + manual adjustments is the way to go. I don’t want to make this too overly complicated.

it does look like there’s still some headroom to improve normalization performance using the GPU. I just want to ensure it’s nothing vendor specific.

3 Likes

Yeah I think you’re on to something with the zero motion training- I have noticed sections lacking scripting entirely in the latest version while the 0.1.0 goblins were eager enough to still try and often get close.

Definitely seeing more artifacts in the latest versions, and while I’m not often loading up videos with super fast motion… it can sometimes add random fast motions anyway. It still works quite well though, to be fair.

It would be cool to be able to feed the goblins our own training sets (I want to be able to run 2D, 2.5D, and 3D with high accuracy) but I don’t know where to even start that workflow.

1 Like

That makes sense. For the crop workflow, we meant letting GoblinScript perform auto-crop and generate the first script normally. The browser review page could then provide a simple “adjust crop and regenerate” button. The automatic area may be too small and miss useful movement, or too large and retain too much unrelated detail. A low-confidence or unusually small-motion result could suggest checking the crop, without making the normal workflow more complicated.

We also agree that GPU normalization should not be tied to one manufacturer. Since GoblinScript already depends on FFmpeg, the same feature could select whichever GPU processing path FFmpeg reports as available, while retaining the current CPU fallback. The user would not need to know whether the computer uses NVIDIA, AMD, or Intel. We can help test the same approach on other hardware.

While checking the v0.3.5 source, we noticed one small inconsistency: HwAccel::On says that hardware decoding should be attempted for every source, but -hwaccel auto is currently added only inside the VR branch. It therefore appears that flat videos do not actually receive hardware decoding even with --hwaccel on. This may simply be a small oversight, but we thought it was worth mentioning.

We look forward to testing the next version.

1 Like

Hello everyone,

I wanted to congratulate gagax123 for the wonderful software that is GoblinScript, it’s impressive!

For those who have tried it, I wanted to know how well the “goblins” handle detecting JAV VR videos that feature mosaics. Does that interfere much with motion detection?

Thanks in advance.

3 Likes

This raises a good point actually.

There is a creator that comes to mind who creates some fantastic funscripts for both censored and de-censored versions of JAV VR videos.

It would be very interesting to see what the goblins produce for both versions of the video. Unfortunately I’m busy for the foreseeable future so I won’t get chance to take a look at this for a while myself.

1 Like

Woah, this is incredible! The results are good enough to enjoy pretty much any video right away. Thanks a lot for this, it’s a gamechanger! One area where it could work a little better is pulling out completely and going back in, often it doesn’t even recognize that as a stroke. But still, absolutely amazing stuff!

3 Likes

I have no idea but I assume it handicaps the model
decensoring may help there but that is just speculation

1 Like

Thanks garbagepailkid for your reply.

1 Like

Thanks gagax123 for your reply. As you say, decensoring should help, but I think that depends on it being done well. It’s a fairly recent development that is evolving rapidly.

1 Like

added another build where you can adjust the crop rects

4 Likes

Hello goblins!

Thank you for v0.3.6. The crop editor, the more precise framing, and the new per-video hardware-decode timing are all genuinely useful updates. Our little Chinese-speaking crew is especially happy that we can now see and adjust exactly what the goblins will watch before they begin.

While testing the Chinese interface, we noticed one small cosmetic issue in the terminal picker. Because CJK labels use double-width characters, the footer key guide can sometimes leave one short item alone on the final row, even though moving the preceding item down would make the two rows look more balanced.

The relevant code is in src/tui.rs, v0.3.6 lines 2120–2150, in pack_lines. Our change is to keep the footer items separate until wrapping is finished, and then move the preceding item down when the final row contains only one item and the two items fit together. The complete replacement function is:

fn pack_lines(
    items: Vec<Vec<Span<'static>>>,
    sep: &str,
    width: u16,
    max_rows: usize,
) -> Vec<Line<'static>> {
    let w = width.max(8) as usize;
    let span_w = |s: &[Span<'static>]| s.iter().map(|x| cols(&x.content)).sum::<usize>();
    let sep_w = cols(sep);
    let (mut rows, mut cur, mut cw) =
        (Vec::<Vec<Vec<Span<'static>>>>::new(), Vec::new(), 0usize);

    for it in items {
        let n = span_w(&it);
        if cur.is_empty() {
            cur.push(it);
            cw = 1 + n;
        } else if cw + sep_w + n > w {
            rows.push(std::mem::take(&mut cur));
            cur.push(it);
            cw = 1 + n;
        } else {
            cur.push(it);
            cw += sep_w + n;
        }
    }
    if !cur.is_empty() {
        rows.push(cur);
    }
    rows.truncate(max_rows.max(1));

    if rows.len() >= 2 {
        let last = rows.len() - 1;
        if rows[last].len() == 1 && rows[last - 1].len() > 1 {
            let candidate = rows[last - 1].last().expect("non-empty row");
            let last_w = 1 + span_w(candidate) + sep_w + span_w(&rows[last][0]);
            if last_w <= w {
                let candidate = rows[last - 1].pop().expect("non-empty row");
                rows[last].insert(0, candidate);
            }
        }
    }

    rows
        .into_iter()
        .map(|row| {
            let mut spans = vec![Span::raw(" ")];
            for (i, item) in row.into_iter().enumerate() {
                if i != 0 {
                    spans.push(Span::raw(sep.to_string()));
                }
                spans.extend(item);
            }
            Line::from(spans)
        })
        .collect()
}

This is not urgent at all, so please do not feel any need to make a release just for it. If it looks useful, perhaps it can simply ride along with whatever the goblins update next. We tested it with the existing footer tests and with a small Chinese double-width case.

One separate question: would it be possible to offer a gentler resource mode, or perhaps leave about 20% of the CPU and GPU available by default where practical, with full-speed processing as an option? One unfortunate goblin in our group ran GoblinScript under heavy load for two days on a Ryzen 9 5900X machine, and it behaved normally throughout the run. After the work was finished, the computer was shut down normally. Problems began the next time it was powered on: it became difficult to boot and then started freezing or crashing frequently. We do not think this proves that GoblinScript itself caused the problem — the machine may already have had a cooling, power, or hardware fault — but the sustained load may have been the final straw. We also understand that an exact 80% limit may not be practical across FFmpeg, DirectML, and different hardware, so a lower-concurrency or periodic-yielding option would also be useful if that is the more realistic approach.

The little goblin den in China is enjoying the new crop window — the goblins can now be shown exactly where to look, a rare privilege for goblins and humans alike.

I don’t think that’s possible. You want the GPU to be under a constant load (no spikes) so running it at a 100% is good also for the health of the GPU. However if the cooling is insufficient or you find it’s getting too hot in your room you need lower the power target of the GPU.
I’ve been running my 4090 at just 50% power target which makes it slower but also draw less power produce less heat. It’s a driver setting in the nvidia app. I’m sure other gpu vendors have the same

1 Like

That makes sense, and lowering the GPU power target is very practical advice. Thank you.

In this particular case, the machine had a Ryzen 9 5900X and was processing a large folder continuously for about two days. The run itself completed normally; the boot problems and frequent crashes only began after the computer had been shut down and powered on again. We cannot know whether the CPU was involved — it could also have been cooling, power delivery, memory, or some pre-existing instability — but a long batch may have kept both the CPU and GPU under sustained load and exposed an existing weakness.

Would it be worth adding one short caution to the documentation instead? Something like: large unattended batches may keep the CPU and GPU under sustained load for many hours, so users should make sure their cooling is adequate, monitor temperatures, and consider a lower GPU power target if necessary.

That may be enough to save the next less fortunate goblin.

Update: the 5900X has now officially gone to goblin heaven. After-sales support confirmed that the CPU had failed. He had been using a version earlier than 0.35, so the most likely explanation is that the long sustained CPU-heavy workload exposed or accelerated the failure.

2 Likes

A small follow-up correction to the pack_lines code above:

After further testing in the classic Windows console, we found that a double-width CJK glyph beginning immediately after a one-cell left inset can sometimes be repainted with a doubled or ghosted first character. This affected footer rows beginning with labels such as 已选 and 上/下.

The balancing logic is still valid, but the footer should consistently reserve two plain cells on the left:

let left_w = 2usize;

Use that value in both new-row width assignments:

cw = left_w + n;

and in the orphan-balancing calculation:

let last_w =
    left_w + span_w(candidate) + sep_w + span_w(&rows[last][0]);

Finally, render the same two-cell inset:

let mut spans = vec![Span::raw("  ")];

It is important that the packing calculations and the rendered prefix use the same inset. We also added a Chinese picker regression test that verifies both blank cells before a footer’s first wide glyph.

One additional hardware follow-up: the user whose CPU appeared to fail has managed to revive it—with what he jokingly calls a little necromancy. After repeated troubleshooting, he traced the instability to a suspected defective core on CCD1. Disabling the affected core or core group brought the 12-core processor back in a roughly 10-core configuration.

That machine had already suffered frequent crashes long before GoblinScript and had reportedly spent years running above 1.41 V. Given that history, the evidence now points much more strongly to a pre-existing unstable or degraded processor than to GoblinScript itself.

I would suggest a general warning that users who already know their processor is unstable, degraded, or unusually voltage-dependent should avoid leaving it under sustained heavy load for long periods.

I also have one suggestion concerning the manual crop-confirmation page added in v0.3.6—the option exposed as K in the picker. After spending more time with the automatic cropper, its results have generally been very good. I would recommend keeping manual crop confirmation disabled by default, since most batches should not be interrupted when the automatic result is already suitable. Users who want to inspect or adjust every crop could still enable it explicitly when needed.

On a separate positive note, we have now spent more time testing the GPU optimizations in v0.3.6, and the performance has been excellent. The improvement is very noticeable in real use, and our little goblin den is extremely happy with how well this version runs.

Thank you again for the great work!

1 Like

Woohoo! Managed to get this built on Linux. Thank you for making this :3

1 Like

so the update with where you can select the focus is what i was talking about before, i just dont think i worded it right. this feature is awesome. i have rerun a few scripts that have like weird gaps or just seemed off with now the manual focus and it is a vast improvement. this software is awesome man. keep up the good work.

I would love it If you could do a writeup of how you got this built in Linux, I am totally into the vibe of this project and would love to contribute to…just don’t want to reinvent the wheel too.

I pushed a new update

3 Likes

If you install cargo and copy the project using git, you can run the cargo build command listed in the README.md in the directory that then builds the project for you !

It does everything automatically and will build a file you can then run using your terminal.

However, I unfortunately did not figure out how to actually get it to work for me. Although the app runs, it is unable to process videos. Since the project uses DirectML, I had to use the cuda feature that was listed in its documentation as working. But when building with cuda enabled, it kept falling back to the CPU. I suspect this is because I have a Blackwell card, and Linux may not have the appropriate software needed for goblinscript to interface with my GPU. Your experience may be different if you’re using a different card !

1 Like

This is amazing. This the first time I’m using a tool like this and it actually does what the others claim to. Even the untouched output is like 90-95% of the way there. Thanks for making it and sharing it.

2 Likes