Views
Pre-built Views
vuer-m3u ships with a small set of views covering the common robotics + ML data types. Every view resolves its clock from the nearest <ClockProvider>, so you only need to wire src in the typical case.
Overview
| View | Compatible dtype(s) | Hooks | Source rate (suggested) |
|---|---|---|---|
| ImuChartView | imu_6dof, vector | useMergedTrack + 60fps Canvas | 50–200 Hz |
| ImuGizmoView | imu_6dof | useMergedTrack + useTrackSample (lerp) | 50–200 Hz |
| JointAngleView | joint_angles | useMergedTrack + useTrackSample (lerp) | 30–250 Hz |
| PoseView | pose_6dof | useMergedTrack + two useTrackSample (lerp + slerpQuat) | 30–120 Hz |
| ActionLabelView | action_label | useSegment + usePlaylist | event-driven |
| VideoPlayer | video | — (hls.js) | — |
| DetectionBoxView | detection_2d | useSegment | event-driven |
| SubtitleView | subtitle | useSegment | event-driven |
| BarTrackView | any continuous dtype — scalar, vector, joint_angles, imu_6dof, pose_6dof | useMergedTrack + useTrackSample (lerp) | any |
| URDF Robot (integration) | joint_angles | useJointAnglesForUrdf | 30–250 Hz |
Per-dtype JSONL schemas live on the Dtypes pages.
Two ways to use a view
1. Direct import — pick the view yourself
Simplest path. Import the view component by name and pass it a src:
import { JointAngleView } from '@vuer-ai/vuer-m3u'
<JointAngleView src="/robot/qpos.m3u8" />Great when you know exactly which view fits the track. Views resolve their clock from <ClockProvider> automatically.
2. Dispatch by dtype — <TrackerContainer>
When you have a list of tracks and want one view per track, let the container dispatch:
import {
TrackerContainer,
defaultTrackerViews,
type TimelineConfig,
} from '@vuer-ai/vuer-m3u'
const config: TimelineConfig = {
container: { id: 'ep1', duration: 30 },
tracks: [
{ id: 'q', path: 'robot/arm', dtype: 'joint_angles', src: '/q.m3u8' },
{ id: 'imu', path: 'sensors/imu', dtype: 'imu_6dof', src: '/imu.m3u8' },
{ id: 'cam', path: 'cams/wrist', dtype: 'video', src: '/cam.m3u8' },
],
}
<TrackerContainer config={config} views={defaultTrackerViews} controller />defaultTrackerViews wires dtype → view:
| Dtype | View |
|---|---|
video | VideoPlayer |
subtitle | SubtitleView |
scalar / vector | BarTrackView |
imu_6dof | ImuChartView |
joint_angles | JointAngleView |
pose_6dof | PoseView |
action_label | ActionLabelView |
detection_2d | DetectionBoxView |
Dtypes without an entry (audio, image, marker_event, ribbon_state) render a placeholder instead — ship your own by spreading a view in, or use <TimelineContainer> where every built-in dtype has a default lane.
Override a subset by spreading:
views={{ ...defaultTrackerViews, imu_6dof: ImuGizmoView }}Same config, two containers
<TrackerContainer> and <TimelineContainer> take the same TimelineConfig. One data object, two presentations — swap components to swap the view mode:
const [mode, setMode] = useState<'tracker' | 'timeline'>('tracker')
return mode === 'tracker'
? <TrackerContainer config={config} views={defaultTrackerViews} />
: <TimelineContainer config={config} views={defaultTimelineViews} />Both containers resolve clock identically (prop → context → internal). Wrap them in a single <ClockProvider> and play/seek syncs across both.
Choosing a view
- Discrete vs continuous — if each segment is a self-contained list (events, cues), use a
useSegmentview. If the data is a dense time-series you want to scrub and interpolate, use auseMergedTrackview. - Interpolator — quaternion data must go through
slerpQuatto avoid non-unit intermediates; that's whyPoseViewsplitsdataintopositionandorientationtracks internally. - Render rate — the views default to 15–30 fps React updates. Tune via the
fpsprop if you need a faster scrubber or a quieter display.
Not finding what you need?
See Custom Views for step-by-step mini implementations built from the same four core hooks, and a checklist for adding a new view (including the companion doc page).