Improve jsmpeg player websocket handling (#21943)

* improve jsmpeg player websocket handling

prevent websocket console messages from appearing when player is destroyed

* reformat files after ruff upgrade
This commit is contained in:
Josh Hawkins 2026-02-09 10:54:45 -06:00 committed by GitHub
parent b0c16dcfaa
commit 8d82ac8376
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 36 additions and 17 deletions

View File

@ -71,7 +71,7 @@ def get_faces():
face_dict[name] = [] face_dict[name] = []
for file in filter( for file in filter(
lambda f: (f.lower().endswith((".webp", ".png", ".jpg", ".jpeg"))), lambda f: f.lower().endswith((".webp", ".png", ".jpg", ".jpeg")),
os.listdir(face_dir), os.listdir(face_dir),
): ):
face_dict[name].append(file) face_dict[name].append(file)
@ -580,7 +580,7 @@ def get_classification_dataset(name: str):
dataset_dict[category_name] = [] dataset_dict[category_name] = []
for file in filter( for file in filter(
lambda f: (f.lower().endswith((".webp", ".png", ".jpg", ".jpeg"))), lambda f: f.lower().endswith((".webp", ".png", ".jpg", ".jpeg")),
os.listdir(category_dir), os.listdir(category_dir),
): ):
dataset_dict[category_name].append(file) dataset_dict[category_name].append(file)
@ -638,7 +638,7 @@ def get_classification_images(name: str):
status_code=200, status_code=200,
content=list( content=list(
filter( filter(
lambda f: (f.lower().endswith((".webp", ".png", ".jpg", ".jpeg"))), lambda f: f.lower().endswith((".webp", ".png", ".jpg", ".jpeg")),
os.listdir(train_dir), os.listdir(train_dir),
) )
), ),

View File

@ -642,7 +642,7 @@ def write_classification_attempt(
# delete oldest face image if maximum is reached # delete oldest face image if maximum is reached
try: try:
files = sorted( files = sorted(
filter(lambda f: (f.endswith(".webp")), os.listdir(folder)), filter(lambda f: f.endswith(".webp"), os.listdir(folder)),
key=lambda f: os.path.getctime(os.path.join(folder, f)), key=lambda f: os.path.getctime(os.path.join(folder, f)),
reverse=True, reverse=True,
) )

View File

@ -539,7 +539,7 @@ class FaceRealTimeProcessor(RealTimeProcessorApi):
cv2.imwrite(file, frame) cv2.imwrite(file, frame)
files = sorted( files = sorted(
filter(lambda f: (f.endswith(".webp")), os.listdir(folder)), filter(lambda f: f.endswith(".webp"), os.listdir(folder)),
key=lambda f: os.path.getctime(os.path.join(folder, f)), key=lambda f: os.path.getctime(os.path.join(folder, f)),
reverse=True, reverse=True,
) )

View File

@ -26,15 +26,16 @@ LOG_HANDLER.setFormatter(
# filter out norfair warning # filter out norfair warning
LOG_HANDLER.addFilter( LOG_HANDLER.addFilter(
lambda record: not record.getMessage().startswith( lambda record: (
"You are using a scalar distance function" not record.getMessage().startswith("You are using a scalar distance function")
) )
) )
# filter out tflite logging # filter out tflite logging
LOG_HANDLER.addFilter( LOG_HANDLER.addFilter(
lambda record: "Created TensorFlow Lite XNNPACK delegate for CPU." lambda record: (
not in record.getMessage() "Created TensorFlow Lite XNNPACK delegate for CPU." not in record.getMessage()
)
) )

View File

@ -194,8 +194,10 @@ class RecordingMaintainer(threading.Thread):
processed_segment_count = len( processed_segment_count = len(
list( list(
filter( filter(
lambda r: r["start_time"].timestamp() lambda r: (
< most_recently_processed_frame_time, r["start_time"].timestamp()
< most_recently_processed_frame_time
),
grouped_recordings[camera], grouped_recordings[camera],
) )
) )

View File

@ -118,6 +118,8 @@ export default function JSMpegPlayer({
const videoWrapper = videoRef.current; const videoWrapper = videoRef.current;
const canvas = canvasRef.current; const canvas = canvasRef.current;
let videoElement: JSMpeg.VideoElement | null = null; let videoElement: JSMpeg.VideoElement | null = null;
let socket: WebSocket | null = null;
let socketMessageHandler: ((event: MessageEvent) => void) | null = null;
let frameCount = 0; let frameCount = 0;
@ -152,12 +154,14 @@ export default function JSMpegPlayer({
videoElement.player.source && videoElement.player.source &&
videoElement.player.source.socket videoElement.player.source.socket
) { ) {
const socket = videoElement.player.source.socket; socket = videoElement.player.source.socket as WebSocket;
socket.addEventListener("message", (event: MessageEvent) => { socketMessageHandler = (event: MessageEvent) => {
if (event.data instanceof ArrayBuffer) { if (event.data instanceof ArrayBuffer) {
bytesReceivedRef.current += event.data.byteLength; bytesReceivedRef.current += event.data.byteLength;
} }
}); };
socket.addEventListener("message", socketMessageHandler);
} }
// Update stats every second // Update stats every second
@ -197,11 +201,23 @@ export default function JSMpegPlayer({
} }
if (videoElement) { if (videoElement) {
try { try {
// this causes issues in react strict mode videoElement.player?.destroy();
// https://stackoverflow.com/questions/76822128/issue-with-cycjimmy-jsmpeg-player-in-react-18-cannot-read-properties-of-null-o
videoElement.destroy();
// eslint-disable-next-line no-empty // eslint-disable-next-line no-empty
} catch (e) {} } catch (e) {}
if (videoWrapper) {
videoWrapper.innerHTML = "";
// @ts-expect-error playerInstance is set by jsmpeg
videoWrapper.playerInstance = null;
}
}
if (socket) {
if (socketMessageHandler) {
socket.removeEventListener("message", socketMessageHandler);
}
socket = null;
socketMessageHandler = null;
} }
}; };
} }