Present replay 3D with the cursor and open Analyze on a remembered video

Replay left the 3D pane on the rest mesh or a sparse overlay, and Analyze skipped the setup dialog unless the file was re-picked. Live Run no longer starts a chain on a video path. Verified with Studio tests for flush, overlay mask, Analyze open, live-video refusal, and locales.
This commit is contained in:
ykcheungab
2026-10-05 16:52:27 +08:00
parent 3433eb0fec
commit c0a10e6adb
26 changed files with 2226 additions and 158 deletions
+57 -44
View File
@@ -2,8 +2,7 @@
"app": {
"title": "Orisys Studio",
"about_title": "About",
"about_body": "Orisys Studio desktop application\nVersion: {app_version}",
"scaffold_hint": "Scaffold shell — acquisition coming later"
"about_body": "Orisys Studio desktop application\nVersion: {app_version}"
},
"brand": {
"name": "ORISYS",
@@ -40,8 +39,10 @@
"settings": "Settings area",
"plot_settings": "Plot settings…",
"rotate_arrows": "Rotate arrows 90°",
"recompute": "Recompute forces from the video",
"recompute_tip": "Off: the charts read the recorded forces.csv. On: re-run the vision pipeline over the recorded video (an algorithm check, forward-only).",
"recompute": "Analyze video",
"recompute_tip": "On: serve a stored analysis result for this video, or run the pass if there is none. Off: leave analysis and read the recording’s own forces.csv when it has one. To change profile, calibration or reference frame use View ▸ Analysis setup…",
"analysis_setup": "Analysis setup…",
"analysis_setup_tip": "Choose the profile, calibration and reference frame for this video, then run (or re-run) the analysis pass.",
"run": "Run / Stop",
"stop": "Cancel acquisition",
"preview": "Preview / Stop preview",
@@ -113,8 +114,8 @@
"use_camera_tip": "Go back to acquiring from a camera (the data source is a video file)",
"choose_video": "Choose a recorded video…",
"choose_video_tip": "Open a recorded video: the 2D panel plays it and the charts read the forces.csv beside it",
"recompute": "Recompute from video…",
"recompute_tip": "Run the pipeline over this recording again: the 2D panel then shows the processed image (the recording itself stores only the raw camera image) and the charts and 3D view use the recomputed values. You can press Stop at any time.",
"recompute": "Analyze video…",
"recompute_tip": "Serve a stored analysis result for this video, or run the pass if there is none. The 2D panel can then draw arrows and depth; the charts may show force from the result. Stop cancels a pass that is still running. To change profile, calibration or reference frame use View ▸ Analysis setup…",
"replay_view_only": "Open a recording from the History replay view",
"preview": "Preview",
"preview_stop": "Stop preview",
@@ -126,13 +127,14 @@
"cancel_tip": "Abort the connection (always available while connecting, shortcut Esc)",
"run_unavailable": "Not available yet",
"run_disabled_video": "Select a video file first",
"run_video_in_replay": "Play a video from the History replay view (Play and the chart cursor)",
"run_disabled_sensor": "Run is not available for this sensor type",
"playback": "▶ Play",
"playback_pause": "⏸ Pause",
"playback_tip": "Play this recording at 1× (space bar does the same); dragging the cursor pauses",
"playback_pause_tip": "Pause playback (dragging the cursor, box zoom or the wheel also pauses)",
"playback_disabled": "Open a recorded video first (“Choose a recorded video…” at the top left)",
"playback_needs_recording": "This video has no recording beside it (no forces.csv): replay needs a recording; to just watch the video use View ▸ Recompute forces from the video",
"playback_needs_recording": "This video has no recording beside it (no forces.csv): replay needs a recording; to just watch the video open it as a video, or use View ▸ Analyze video",
"playback_video_only": "Play this video (no recording beside it: the picture plays, the force charts are empty)",
"reset_sensor": "Reset sensor",
"reset_sensor_tip": "Zero the sensor tracker (the device's own zero). Zeroing it also restarts the display baseline, so the curves and the value cards re-learn their zero from the next quiet samples; the curve history is kept — View ▸ Reset views (F8) clears the views.",
@@ -140,7 +142,6 @@
"reset_display": "Reset display",
"reset_display_tip": "Clear the accumulated display: the curves, cursor and value cards go back to their defaults and the replay returns to the start of the recording. There is no device session in this view, so nothing of the device is touched; the 3D camera is View ▸ Reset views (F8).",
"pause": "⏸ Pause",
"pause_resume": "▶",
"pause_tip": "Pause the computation and the display (F7): no flow, depth or contact is computed, the picture holds its last frame, and the device stays connected for an immediate resume. A recording that spans a pause has a gap.",
"resume_tip": "Resume the computation and the display (F7), from the newest frame.",
"resume_label": "▶ Resume",
@@ -155,8 +156,7 @@
"units_newton": "Newton",
"units_raw": "Raw",
"settings": "Settings",
"settings_tip": "Show or hide the unit, record-mode and preview controls",
"stopped_analysis": "analysis"
"settings_tip": "Show or hide the unit, record-mode and preview controls"
},
"units": {
"newton_short": "N",
@@ -181,11 +181,24 @@
"export_identity": "file identity type {sensor_type} · SN {sn} · config {config}",
"thumb_placeholder": "Product model",
"family_unidentified": "Unidentified",
"catalog_profile": "Profile {profile_id} · {shape} · from {origin} · SDK validation: {state}",
"catalog_name": "name {name} · folder {folder}",
"catalog_profile": "Profile {profile_id} · {shape} · from {origin}",
"catalog_root": "root {origin}: {path}",
"catalog_state": "SDK validation: {state} ({note})",
"catalog_state_ok": "processing can start",
"catalog_state_degraded": "processing can start; something optional is missing",
"catalog_state_failed": "processing cannot start",
"catalog_state_invalid": "no bundle could be read here",
"catalog_state_unknown": "verdict not recognised",
"catalog_calibration_selected": "Calibration selected: {name}",
"catalog_calibration_none": "No calibration selected — raw force",
"catalog_duplicate": "Also provided by {refs}",
"catalog_shape_descriptor": "descriptor bundle",
"catalog_shape_compatibility": "compatibility bundle, no descriptor",
"catalog_shape_unreadable": "no readable bundle",
"catalog_blocked": "Cannot start: {reason}"
"catalog_blocked": "Cannot start: {reason}",
"catalog_warning": "Warning: {sentence}",
"catalog_error": "Error: {sentence}"
},
"panels": {
"arrow": "2D image",
@@ -195,8 +208,8 @@
"view_recorded": "Recorded image",
"view_mode_tip": "Image display mode while running",
"replay_pipeline": "Recorded video (raw camera image)",
"replay_pipeline_tip": "Replay shows the recorded raw camera image with no live arrow overlay; to check the algorithm, use View → Recompute forces from the video",
"replay_raw_note": "A recording stores only the raw camera image: there is no flow or depth to draw, because this recording has no analysis result yet. Opening a recording runs the pass automatically, or press “Recompute from the video”; once a result exists this pane can draw arrows and the depth map",
"replay_pipeline_tip": "Replay shows the recorded raw camera image with no live arrow overlay; to get arrows and depth from analysis, use View → Analyze video",
"replay_raw_note": "A recording stores only the raw camera image: there is no flow or depth to draw, because this recording has no analysis result yet. Opening a recording runs the pass automatically, or press “Analyze video”; once a result exists this pane can draw arrows and the depth map",
"frame_missing_note": "This frame carries no {fields}: there is nothing for this view to draw",
"field_flow": "flow",
"field_depth": "depth",
@@ -227,12 +240,9 @@
"mesh3d_unavailable_gl_reason": "3D is not available on this machine: {reason}\nMeasuring, recording and the charts work as usual.",
"mesh3d_settings_tip": "3D display settings (view, housing, colour scale, frame rate)",
"mesh3d_reset_tip": "Reset view: back to the framing the scene itself uses",
"analysis_pipeline": "Analysis result (one finished pass)",
"analysis_pipeline_tip": "This frame's arrows come from a stored analysis result rather than a chain running now; changing the threshold only changes which stored samples count as active.",
"analysis_empty": "the analysis result holds no frame here",
"replay_analysis_running": "this recording is being analysed: there are no arrows or depth to draw until it finishes. Progress and Cancel are on the analysis panel.",
"replay_analysis_failed": "there is no analysis result to draw: {reason}. Only the raw camera image can be shown here; once that is dealt with, Recompute from the video runs the pass again by hand.",
"replay_analysis_unavailable": "this is not a recording that can be analysed (its folder has no session.json, or no raw_*.mp4 segment): no pass can run, so this panel shows the raw camera image only. For forces and deformation from this video use View > Recompute forces from the video."
"replay_analysis_failed": "there is no analysis result to draw: {reason}. Only the raw camera image can be shown here; once that is dealt with, Analyze video runs the pass again by hand.",
"replay_analysis_unavailable": "this is not a recording that can be analysed (its folder has no session.json, or no raw_*.mp4 segment): no pass can run, so this panel shows the raw camera image only. For forces and deformation from this video use View > Analyze video."
},
"chart": {
"fn": "FN",
@@ -250,6 +260,12 @@
"mode_browse_tip": "Display paused, capture and recording continue; drag or scroll to move the window, “back to latest” returns to live",
"mode_replay": "Replaying a recording (browsing)",
"mode_replay_tip": "The charts read the open recording; capture and recording continue",
"mode_recomputed": "Recomputed from this video (browsing)",
"mode_recomputed_tip": "The charts read the force the analysis pass recomputed from this video and stored in its result. This is not the recorded forces.csv — no device measured these numbers",
"mode_no_trace": "No force trace — {reason}",
"mode_no_trace_tip": "There is nothing to plot, and the reason is a fact about the input rather than a loading state",
"trace_not_analysed": "this video has not been analysed yet",
"trace_no_force": "this profile's chain produced no force for this video",
"return_latest": "Back to latest",
"return_latest_tip": "Leave history browsing and follow the newest data again",
"overview": "Whole session",
@@ -272,15 +288,14 @@
"browse_only_tip": "Drag or scroll on the chart to browse history"
},
"playback": {
"title": "Replay recording",
"open": "Open a recorded video…",
"video_filter": "Recorded video (*.mp4 *.avi *.mov *.mkv);;All files (*)",
"no_video": "This recording has no usable video segment",
"open_failed": "Could not open that recording: {error}",
"not_a_recording": "“{name}” is not a recording: its folder has no forces.csv (a recording is the video plus forces.csv and session.json). Replay needs a recording; to just watch this video, use “Recompute forces from the video”.",
"video_only_opened": "“{name}” has no recording beside it (no forces.csv), so it is playing as a video: the picture and the timeline work, the force charts are empty. For forces and deformation use View ▸ Recompute forces from the video.",
"not_a_recording": "“{name}” is not a recording: its folder has no forces.csv (a recording is the video plus forces.csv and session.json). Replay needs a recording; to just watch this video, open it as a video or use View ▸ Analyze video.",
"video_only_opened": "“{name}” has no recording beside it (no forces.csv), so it is playing as a video: the picture and the timeline work, the force charts are empty. For forces and deformation use View ▸ Analyze video.",
"video_only_notice": "This video has no recording beside it (no forces.csv): it plays, but the force charts and the recording details are empty.",
"video_only_panel": "This is not a recording, and this video cannot be decoded (no forces.csv beside it, and it does not read as playable video)\nYou can still try View ▸ Recompute forces from the video",
"video_only_panel": "This is not a recording, and this video cannot be decoded (no forces.csv beside it, and it does not read as playable video)\nYou can still try View ▸ Analyze video",
"empty_recording": "This recording has no playable picture (no raw_*.mp4 segment), so it cannot be replayed",
"none_found": "No recording found under outputs/recordings",
"frame_dropped": "This frame never reached the video (the record queue overflowed)",
@@ -295,17 +310,28 @@
"warn_out_of_order": "this recording was written by an older version: its rows are not in time order, so the replay re-sorts them and window edges may differ",
"analysis_empty": "this analysis result holds no frame to show",
"analysis_unreadable": "this frame cannot be read ({error})",
"analysis_complete": "replaying from the analysis result: {frames} frames, cursor on signal time (the recording's own frames.csv)",
"analysis_reused": "an analysis result was already stored and is being replayed: {frames} frames",
"analysis_failed": "the analysis did not finish ({reason}): playback is not served. Re-run it, or turn 「从视频重算」 off to read the recorded forces.csv",
"analysis_cancelled": "the analysis was cancelled: no complete result was written, so no playback is served",
"analysis_no_source": "this recording has no video segment to analyse",
"analysis_busy": "an analysis is already running: wait for it, or cancel it",
"analysis_grid_mismatch": "the current display settings moved the sample grid ({keys}); the stored candidate locations cannot serve it, so the replay keeps drawing the result's own grid",
"analysis_no_chain": "this recording does not say which sensor and configuration produced it ({error}), so no result can be read and no pass can be run"
"analysis_no_chain": "this recording does not say which sensor and configuration produced it ({error}), so no result can be read and no pass can be run",
"analysis_setup_declined": "no analysis was set up for this video: the setup prompt was dismissed, so there is nothing to draw from. Use View ▸ Analysis setup… or open the video again"
},
"video_analysis": {
"title": "Analyse this video",
"video": "{name} — {frames} frames at {fps} fps ({seconds} s). It has no recording beside it (no forces.csv, no frames.csv), so the pass will work from a frame index generated for it.",
"profile": "Processing profile",
"calibration": "Calibration",
"calibration_default": "Profile default — {name}",
"calibration_none": "No calibration — raw force",
"calibration_file": "Chosen file — {name}",
"calibration_browse": "Choose a file…",
"calibration_filter": "Force calibration (*.json);;All files (*)",
"reference": "Reference frame",
"reference_time": "{seconds} s",
"blocked": "This profile cannot be used: {reason}"
},
"record": {
"label": "Record",
"mode_video_data": "Video + data",
"mode_data_only": "Data only",
"mode_tip": "Video records the pre-processing camera input (no arrows or text overlays). MP4 is a lossy container, not a lossless copy of the raw data.",
@@ -319,7 +345,6 @@
"finished": "Recording finished — {frames} frames / {segments} segment(s) in {path}",
"finished_with_problems": "Recording finished with problems: {detail}",
"closing": "Closing the recording files…",
"failed_state": "The recording failed (see the summary and the log)",
"alarm": "Recording problem: {detail}",
"state_idle": "No recording",
"state_recording": "Recording {duration}",
@@ -373,9 +398,6 @@
"col_fy": "FY mean",
"col_stability": "Stability",
"col_state": "State",
"col_raw": "Raw mean",
"col_n": "n",
"col_std": "σ",
"state_ok": "OK",
"state_excluded": "Excluded",
"state_validation": "Validation",
@@ -403,13 +425,11 @@
"point_samples_value": "{valid} valid / {total} total",
"point_axes": "Three-axis mean ± std",
"point_residual": "Fit residual",
"col_actions": "",
"recording": "Recording calibration samples…",
"recording_stop_tip": "Click to cancel this calibration recording (always available)",
"record_ok": "Recorded weight={weight} raw={raw}",
"record_failed_few": "Recording failed — too few samples",
"export_ok": "Exported {path}",
"export_local": "Also wrote {path}",
"export_warnings": "Skipped: {detail}",
"export_failed": "Export failed: {error}",
"export_no_model": "Nothing to export: {detail}",
@@ -484,7 +504,6 @@
"contact_arrow_unavailable": "This scene package has no UV→scene surface mapping, so the contact arrow cannot be drawn.",
"quantity_flow_magnitude": "Optical flow magnitude",
"quantity_depth_response": "Depth response",
"mode_surface": "surface colouring",
"preset_default": "Default view",
"legend_effective": "{quantity} [{unit}] · {mode} scale {lower} – {upper} · {quality}",
"legend_auto": "automatic",
@@ -515,9 +534,9 @@
"source_live": "Live acquisition",
"source_live_tip": "The picture comes from the data being acquired right now.",
"source_replay": "Replay: the recording stores no 3D field",
"source_replay_tip": "A recording stores the raw camera image and the forces, not a per-frame deformation field. Turn on “Recompute forces from the video” and this pane will show the deformation recomputed from the recording.",
"source_recompute": "Recomputed from the recording — not the recorded values",
"source_recompute_tip": "This is what the current algorithm version says about the recorded footage: it is a check on the algorithm, not the measurement that was recorded at the time.",
"source_replay_tip": "A recording stores the raw camera image and the forces, not a per-frame deformation field. Turn on Analyze video and this pane will show the deformation from the analysis result.",
"source_recompute": "From the analysis result — not the recorded values",
"source_recompute_tip": "This is what the current algorithm version says about the footage in the stored analysis result: it is not the measurement that was recorded at the time.",
"severity_info": "Note",
"severity_warning": "Warning",
"severity_error": "Error",
@@ -527,21 +546,15 @@
},
"analysis": {
"title": "Analysing the recording",
"subtitle": "once only: scrubbing, playing and stepping afterwards are reads",
"stage_open": "open chain",
"stage_frames": "frame by frame",
"stage_write": "write result",
"frames": "{written} / {expected} frames",
"segment": "segment {index} / {count}",
"elapsed": "{seconds:.1f} s elapsed",
"cancel": "Cancel",
"cancelling": "Cancelling…",
"cancel_tip": "Cancel this pass: the frames already written stay, but the result is marked incomplete and is never played back as if it were whole",
"reused": "a stored result is already there — nothing to recompute",
"complete": "analysis finished: {frames} frames in {seconds:.1f} s",
"cancelled": "analysis cancelled ({frames} frames written; the result is marked incomplete)",
"failed": "analysis failed: {reason}",
"incomplete": "the result is incomplete: {reason}",
"blocked": "a session is running: stop it before analysing"
}
}