Skip to content

Commit cc89e64

Browse files
committed
Merge branch 'main' of https://github.com/eth-ait/aitviewer
2 parents 29df5bb + 1539295 commit cc89e64

2 files changed

Lines changed: 46 additions & 5 deletions

File tree

aitviewer/viewer.py

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Copyright (C) 2022-2026 ETH Zurich, Manuel Kaufmann, Velko Vechev, Dario Mylonopoulos
22
import copy
33
import os
4+
import subprocess
45
import sys
56
from array import array
67
from collections import namedtuple
@@ -31,6 +32,41 @@
3132
from aitviewer.utils.perf_timer import PerfTimer
3233
from aitviewer.utils.utils import get_video_paths, video_to_gif
3334

35+
36+
class FFmpegWriter:
37+
"""Thin ffmpeg pipe writer, replaces scikit-video which broke on NumPy 2.0."""
38+
39+
def __init__(self, path, inputdict, outputdict):
40+
self._path = path
41+
self._inputdict = inputdict
42+
self._outputdict = outputdict
43+
self._proc = None
44+
45+
def _start(self, frame):
46+
h, w = frame.shape[:2]
47+
pix_fmt = "rgba" if frame.ndim == 3 and frame.shape[2] == 4 else "rgb24"
48+
input_args = [a for k, v in self._inputdict.items() for a in (k, str(v))]
49+
output_args = [a for k, v in self._outputdict.items() for a in (k, str(v))]
50+
cmd = (
51+
["ffmpeg", "-y"]
52+
+ input_args
53+
+ ["-f", "rawvideo", "-pix_fmt", pix_fmt, "-s", f"{w}x{h}", "-i", "pipe:0"]
54+
+ output_args
55+
+ [self._path]
56+
)
57+
self._proc = subprocess.Popen(cmd, stdin=subprocess.PIPE)
58+
59+
def writeFrame(self, frame):
60+
if self._proc is None:
61+
self._start(frame)
62+
self._proc.stdin.write(frame.tobytes())
63+
64+
def close(self):
65+
if self._proc is not None:
66+
self._proc.stdin.close()
67+
self._proc.wait()
68+
69+
3470
MeshMouseIntersection = namedtuple(
3571
"MeshMouseIntersection",
3672
"node instance_id tri_id vert_id point_world point_local bc_coords",
@@ -155,6 +191,15 @@ def __init__(
155191
self.window.set_icon(icon_path=icon_path)
156192
except:
157193
pass
194+
if sys.platform == "darwin":
195+
# On macOS the dock icon must be set at the QApplication level.
196+
if self.window_type == "pyqt6":
197+
from PyQt6.QtGui import QIcon
198+
from PyQt6.QtWidgets import QApplication
199+
else:
200+
from PyQt5.QtGui import QIcon
201+
from PyQt5.QtWidgets import QApplication
202+
QApplication.instance().setWindowIcon(QIcon(icon_path))
158203

159204
self.timer = PerfTimer()
160205
self.ctx = self.window.ctx
@@ -1867,9 +1912,6 @@ def export_video(
18671912
quality="medium",
18681913
ensure_no_overwrite=True,
18691914
):
1870-
# Load this module to reduce load time.
1871-
import skvideo.io
1872-
18731915
if rotate_camera and not isinstance(self.scene.camera, ViewerCamera):
18741916
print("Cannot export a video with camera rotation while using a camera that is not a ViewerCamera")
18751917
return
@@ -1965,7 +2007,7 @@ def export_video(
19652007
}
19662008
)
19672009

1968-
writer = skvideo.io.FFmpegWriter(
2010+
writer = FFmpegWriter(
19692011
path_video,
19702012
inputdict={
19712013
"-framerate": str(output_fps),

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ dependencies = [
4040
"roma>=1.2.3",
4141
"joblib",
4242
"scikit-image>=0.9.0",
43-
"scikit-video",
4443
"Pillow",
4544
"websockets",
4645
"usd-core>=23.5",

0 commit comments

Comments
 (0)