how to generate the web app to embed a Viser visualization in another HTML
Hi Brent!
There is a nice embedded 4D demonstration in https://robot-see-robot-do.github.io/
Looks like there's a web app at https://rsrd-anonymous.github.io/build/ that's tailored to run a .viser file. I'm thinking of making my own web app to visualize viser stuff on the web. So, how do I go about designing this web app?
Hi @jhaoshao, thanks for your interest!
Unfortunately this feature isn't fully stable so there's no documentation yet, and my time is currently quite constrained so it's hard to help much. If you want to try and figure it out anyways, I can provide some pointers though:
The main recording function is here. Usage example:
rec = server._start_scene_recording()
rec.set_loop_start()
for t in range(timesteps):
# [some updates here]
rec.insert_sleep(sleep_duration_handler.value)
server.send_file_download(
"recording.viser", content=handle.end_and_serialize()
)
For how to embed you can see the source code for robot-see-robot-do.github.io: https://github.com/robot-see-robot-do/robot-see-robot-do.github.io/blob/7d9c1208e7ece2c1de56391ad6be819b5cbfc053/index.html#L264-L268
The build/ directory that the iframe in there points to is basically just a standard viser client build. You can generate it by installing the client dependencies and running npx vite build --base=/build from src/viser/client/.
Thanks for your timely reply! I'll figure it out
@brentyi Sorry for my (amateur) question, but after building and running viser locally with
cd src/viser/client/
npx vite build
npx vite preview
I figured I could visit
http://localhost:4173/?playbackPath=https://brentyi.github.io/viser-embed-test/trajectories/black_handle_sem.viser
to view an existing .viser file. But in the developer console it looks like the file failed to load:
Do you have any suggestions?
Thanks!
The .viser files are not generally compatible between versions of viser; that file (which I think @AdamRashid96 made for LERF-TOGO?) in particular is around a year old. The "incorrect header check" error is because we weren't saving .viser files in a compressed form at the time.
If you want to just test with an existing .viser file, here's one sequence that I can confirm works for me:
git checkout v0.2.12 # the .viser file below won't work in >v0.2.12
cd src/viser/client
npx vite build
npx vite preview
And then navigate to:
http://localhost:4173/?playbackPath=https://egoallo.github.io/splash-results/feb28_coffeemachine.viser
That worked great, thank you!
I also generated my own .viser file for the 07_record3d_visualizer.py example on the current main branch by replacing the while True loop with
for t in range(num_frames):
point_nodes[t].point_size = gui_point_size.value
rec = server._start_scene_recording()
rec.set_loop_start()
for t in range(num_frames):
gui_timestep.value = t
rec.insert_sleep(1 / 30)
server.send_file_download("recording.viser", content=rec.end_and_serialize())
and I can play it in localhost and everything looks good. However, when I use the scrubber at the bottom to go backwards, all the previous point clouds and camera frustums stay visible and overlap:
https://github.com/user-attachments/assets/ed0698b7-cb31-4239-b277-ed4abee34de4
Do you have any suggestions on how to fix this issue?
The part that worked: great!
The scrubbing problems: this is unfortunately a known issue (#292). You could check if the fix in that issue is performant enough for you; I plan to fix it properly before "releasing" the scene recording features.
With some trial and error you could also hack it with some explicit state resetting immediately after set_loop_start(). I think something like this should work for the snippet you shared (untested):
for t in range(num_frames):
point_nodes[t].point_size = gui_point_size.value
# <new>
# prop updates are ignored if there's no change
# we want to make sure `node.visible = False` is recorded later, to be safe it might help to first set the visibility to `True`
for node in frame_nodes:
node.visible = True
# </new>
rec = server._start_scene_recording()
rec.set_loop_start()
# <new>
for node in frame_nodes:
node.visible = False
# </new>
for t in range(num_frames):
gui_timestep.value = t
rec.insert_sleep(1 / 30)
server.send_file_download("recording.viser", content=rec.end_and_serialize())
Somehow Junyi was also able to work around this for Monst3r but I'm not sure exactly what he did.
Resetting the state totally fixes the issue, thank you!
I'll definitely be staying tuned for the official release of the recording features. This is super useful.
@lahavlipson @brentyi I am trying to generate the .viser file but after running the following code instead of the final while loop as suggested,
for t in range(num_frames):
point_nodes[t].point_size = gui_point_size.value
rec = server._start_scene_recording()
rec.set_loop_start()
for t in range(num_frames):
gui_timestep.value = t
rec.insert_sleep(1 / 30)
server.send_file_download("recording.viser", content=rec.end_and_serialize())
I do not see a .viser file generated. May I ask where is the .viser file being generated?
The send_file_download on this line:
server.send_file_download("recording.viser", content=rec.end_and_serialize())
Should send the file to any connected clients (web browsers), and trigger a download there.
If you'd like to to test that this works you can try running this example: https://github.com/nerfstudio-project/viser/blob/main/examples/19_get_renders.py
If you want you can also just save the file normally:
from pathlib import Path
Path("./some_path.viser").write_bytes(rec.end_and_serialize())
I am a bit confused on how to set build/ on a github page. More specifically, am I suppose to copy build from npx vite build --base=/build and push to a github repo where I can treat as server?
Yeah, it's just a static webpage so you can host it the same way as any other static webpage. Standard GitHub pages is fine.
Some more details:
npx vite buildwill create a local build directory that contains a static webpage (index.html, etc).- The
--base=argument specifies the public base path for the static site. This is used for linking resources (stylesheets, Javascript, etc).- If the build directory gets hosted at
https://projectname.github.io/build/index.html,--base=/buildshould be used. - If the build directory gets hosted at
https://projectname.github.io/viser/index.html(in other words: you rename the folder),--base=/visershould be used. - If the build directory gets hosted at
https://username.github.io/reponame/build/index.html,--base=/reponame/buildshould be used. - etc
- If the build directory gets hosted at
Let me know if that's still unclear!
Thanks for the swift response! My question has been addressed. Thanks!