Skip to content

Vtk streaming encoding#35

Open
Justineantoine wants to merge 6 commits into
masterfrom
vtk-streaming
Open

Vtk streaming encoding#35
Justineantoine wants to merge 6 commits into
masterfrom
vtk-streaming

Conversation

@Justineantoine

@Justineantoine Justineantoine commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Handle video encoding using vtk-streaming lib

Changes:

  • Creates protocol for RCA render schedulers
  • Splits utils.py (still exposing the classes)
  • Splits vtk_utils.py (still exposing the VtkWindow class)
  • Splits test_rca_utils.py
  • Creates tests for video encoding
  • Moved tests dependencies in pyproject.toml
  • Added class names to widgets enabling to overwrite CSS

@Justineantoine Justineantoine marked this pull request as draft June 3, 2026 16:15
@Justineantoine

Copy link
Copy Markdown
Contributor Author

FYI @Thibault-Pelletier @jourdain I am not a fan of the "window" terminology (the interface that handles the interaction and resize events). I remember we briefly discussed this at some point last year, but if you have any new naming ideas, I'd be happy to hear them

@Justineantoine Justineantoine force-pushed the vtk-streaming branch 3 times, most recently from 43c6fcc to 1bf5570 Compare June 3, 2026 19:53
Comment thread pyproject.toml Outdated
Comment thread pyproject.toml
Comment thread src/trame_rca/encoders/video_encoder.py Outdated
Comment thread src/trame_rca/encoders/video_encoder.py Outdated
Comment thread src/trame_rca/encoders/video_encoder.py Outdated
Comment thread src/trame_rca/windows/vtk_image_window.py Outdated
Comment thread src/trame_rca/windows/vtk_video_window.py Outdated
Comment thread src/trame_rca/rca/vtk_rca.py
Comment thread src/trame_rca/utils.py Outdated
Comment thread tests/conftest.py Outdated
@Justineantoine Justineantoine force-pushed the vtk-streaming branch 4 times, most recently from 1c5f358 to fa45020 Compare June 8, 2026 15:56
Comment thread src/trame_rca/windows/protocol.py Outdated
Comment thread src/trame_rca/rca/protocol.py
Comment thread src/trame_rca/windows/protocol.py Outdated
Comment thread src/trame_rca/windows/protocol.py Outdated
Comment thread src/trame_rca/windows/vtk_window.py Outdated
Comment thread examples/05_video/cone_simple_video.py
@jourdain

jourdain commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

In general I like what you've done.

@Justineantoine Justineantoine marked this pull request as ready for review June 10, 2026 09:38
Comment thread src/trame_rca/encoders/video_encoder.py Outdated
Comment thread src/trame_rca/schedulers/video_scheduler.py
Comment thread src/trame_rca/widgets/rca.py Outdated
@Thibault-Pelletier

Copy link
Copy Markdown
Contributor

Just an additional remark on this PR. vtkStreaming is currently leaking when resizing / rebuilding the encoder.
Should we wait for that to be resolved before merging this PR @jourdain ?

@Justineantoine

Copy link
Copy Markdown
Contributor Author

Just an additional remark on this PR. vtkStreaming is currently leaking when resizing / rebuilding the encoder. Should we wait for that to be resolved before merging this PR @jourdain ?

with NVENC, VP9 seems to be ok

@jourdain

Copy link
Copy Markdown
Collaborator

Just an additional remark on this PR. vtkStreaming is currently leaking when resizing / rebuilding the encoder. Should we wait for that to be resolved before merging this PR @jourdain ?

with NVENC, VP9 seems to be ok

Do we know the origin of the leak?

Comment thread examples/01_vtk/vtk_cone_simple_video.py Outdated
Comment thread src/trame_rca/widgets/rca.py Outdated
from weakref import WeakKeyDictionary, WeakValueDictionary

from trame_client.widgets.core import AbstractElement
from vtkmodules.vtkRenderingCore import vtkRenderWindow

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RCA should not force VTK as a dependency.
We should have an easy path to handle vtkRenderWindow but it should not be forced if we plan to use RCA with a custom image generator.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed some imports on this matter. I now can run the vanilla example without having vtk installed. But if you can test on your side that nothing is missing it would be nice

Comment thread vue-components/src/components/RemoteControlledArea.js Outdated
@Justineantoine Justineantoine force-pushed the vtk-streaming branch 4 times, most recently from 44b3cf5 to 52b3afe Compare June 12, 2026 11:36
@AlexyPellegrini

Copy link
Copy Markdown

Just an additional remark on this PR. vtkStreaming is currently leaking when resizing / rebuilding the encoder. Should we wait for that to be resolved before merging this PR @jourdain ?

with NVENC, VP9 seems to be ok

Do we know the origin of the leak?

Working on it, but couldn't find anything useful for now. I would recommend not to use NVENC at all until I fix this...

New available vtk-streaming wheel, v0.3.2, fixes the leak.

chore: rename window protocols and restructure video encoder

feat(css): fix css for video decoder and add class names to components

feat(logger): removed prints for logger info or warning

feat(css): create css file that leverages new class names

fix(rca): fixes video encoder with new wheel and update examples
@Justineantoine

Copy link
Copy Markdown
Contributor Author

Ready to merge @jourdain @Thibault-Pelletier

@Thibault-Pelletier Thibault-Pelletier left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

]

self.name = kwargs.get("name") or f"trame_rca_{RemoteControlledArea._next_id}"
self.display = kwargs.get("display")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to provide a default in case nothing is provided?

self.display = kwargs.get("display", "image")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also do you know that self.display already exist because of that kwargs.

So a better way of writting it could be

def __init__(self, display="image", **kwargs):
        super().__init__(
            "remote-controlled-area",
           display=display,
            **kwargs,
        )

@jourdain

Copy link
Copy Markdown
Collaborator

Looks good, but I guess I'll try it out before merging.

Comment thread src/trame_rca/encoders/video_encoder.py Outdated
Comment thread examples/01_vtk/vtk_cone_simple_video.py Outdated
Comment thread examples/01_vtk/vtk_cone_simple_video.py Outdated
@jspanchu jspanchu force-pushed the vtk-streaming branch 2 times, most recently from edca7a7 to 0f64630 Compare June 12, 2026 20:08
- resizing the frame is sufficient for the encoder to realize that it should shutdown existing session and open a new encoding session.
- there was a bug upstream where setting width/height on the encoder did not bump the MTime of the encoder and so, the frame size was equal to the encoder size and the responsibility of re-initializing the context fell on the MTime logic which was flawed because the encoder did not bump the MTime. As a result, this code needed to manually call `_reset`.
- this has been fixed upstream in Kitware/VTKStreaming#2, so I'm changing the code here.
Comment thread src/trame_rca/encoders/video_encoder.py Outdated
Comment thread examples/01_vtk/vtk_cone_simple_video.py Outdated
Comment thread examples/01_vtk/vtk_cone_simple_video.py

with layout.content:
view = rca.RemoteControlledArea(
display="video-decoder",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On dual screen configuration, using video-decoder generates an image that can overflow (probably due to DPI or scaling ) screenshot below with screen at 125% scaling showing off center cone and overlow scroll PB:

Image

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup, the JS code for VideoDecoder needs reviewed.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow up on this, I think the problem on my side is that we apply the pixel ratio twice (size sent by the browser is already the scaled up version). Commenting out the pixel ratio apply solves the problem and it was just hidden by the JS scaling for the image encoder.

@jourdain do you concur or is there an OS specific thing that may be happening here?

    def update_size(self, origin, size):
        # Resize to ten pixel min to avoid rendering problems
        width = max(10, int(size.get("w", 300)))
        height = max(10, int(size.get("h", 300)))
        pixel_ratio = size.get("p", 1)
        self._current_size = (width, height, pixel_ratio)
        width = int(width * pixel_ratio * self._scale) # <-- incriminated lines
        height = int(height * pixel_ratio * self._scale)

Comment thread src/trame_rca/encoders/__init__.py Outdated
@jspanchu

Copy link
Copy Markdown
Member

I think the fps should not be hard-coded to 30. It gives an awful first impression for first-time users.

Instead, we could be smart about it by getting the client's estimated refresh rate and transmit that to the server.

let last = performance.now(), samples = [];
let fpsEstId;
function tick(now) {
  samples.push(now - last); last = now;
  if (samples.length >= 60) {
    cancelAnimationFrame(fpsEstId);
    const avg = samples.reduce((a,b)=>a+b)/samples.length;
    // ~1000/avg is the refresh rate; send it to the server via state?
  }
  fpsEstId = requestAnimationFrame(tick);
}
fpsEstId = requestAnimationFrame(tick);

@Thibault-Pelletier

Thibault-Pelletier commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

I think the fps should not be hard-coded to 30. It gives an awful first impression for first-time users.

Instead, we could be smart about it by getting the client's estimated refresh rate and transmit that to the server.

The FPS can be manually set by the application to the desired value. It's actually something we do in trame-slicer with the snapshot RCA to limit the bandwidth for non interactive views to 10 FPS (switch is done interactively and can be changed through parameters).

From my tests, 30 FPS works well in deployed applications on AWS with a reasonable bandwidth, but aiming higher may severely slow down the application as the application is not doing rendering only but also computation (although this bottleneck may be removed now that we have vtk streaming / NVENC).

For first time users, we can easily increase the values in the examples. We can also add an option to have a smart FPS, but I would like to also be able to set a fixed target FPS and being able to toggle that from the application layer.

EDIT:
Since RCA is one of many ways to have a trame app running, we can orient users wanting smoother feel to trame-vtk local / VTK WASM.

RCA will remain a bit more sluggish and add in some latency as you would have using any VNC / cloud streaming plateform but from my tests it remains a much nicer experience than using a desktop application (3D Slicer) through an AWS Appstream service.

@Thibault-Pelletier Thibault-Pelletier self-requested a review June 14, 2026 07:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants