Ex: Edit a Recording
Filter or modify a recording’s points and save the result with Python.
This example edits a Voyant recording and saves it back: read each frame, filter or modify its points as a numpy matrix, rebuild the frame with with_points(), and record the result to a new .vynt file. The input file is read-only throughout — the edits land in a new file.
The same flow works on live frames from a CarbonClient: filter or annotate each frame as it arrives, then record it.
Requires pip install voyant-api.
What You’ll Learn
- How to chain
VoyantPlaybackintoVoyantRecorderto rewrite a recording - How to edit the
points()matrix and rebuild a frame withwith_points() - How to stamp the user-owned per-point column (
user_data)
Prerequisites
- Python 3.9 or later
voyant-apiinstalled:pip install voyant-api- A Voyant
.vyntrecording (see Data Recording; convert a pre-v1.0.0 recording withvoyant_recording_migratefirst)
Example Code
View the complete example on GitHub: edit_recording_example.py
Key Concepts
Reader and Writer
Playback is the reader and the recorder is the writer. With keep_invalid_points left False, invalid returns are dropped as frames are read, so the output holds only valid points:
from voyant_api import RecordStatus, VoyantFrame, VoyantPlayback, VoyantRecorder, init_voyant_logging
init_voyant_logging()
COLS = VoyantFrame.points_columns()
playback = VoyantPlayback(keep_invalid_points=False)
playback.open("recording.vynt")
Editing the Points Matrix
frame.points() is a numpy matrix with one column per recorded field — COLS gives the column order. Any numpy edit works. This one keeps points within a range limit and stamps the user-owned column to mark the rows the script touched — the visualizer’s User Data color mode can then highlight them:
matrix = frame.points()
keep = matrix[:, COLS.index("range_m")] <= max_range
matrix = matrix[keep]
matrix[:, COLS.index("user_data")] = 1
Points that arrive as x/y/z — from a ROS cloud, a CSV — go in with cartesian=True, which the library projects back into the stored spherical geometry. Pass the same cartesian to points() and with_points(): a basis mismatch is not detectable, so a Cartesian matrix passed without the flag stores x, y, z into the range and angle fields.
Working from a pandas DataFrame instead? Select columns by name so column order can’t drift: matrix = df[VoyantFrame.points_columns()].to_numpy().
Rebuilding and Recording the Frame
with_points() returns a new frame that keeps everything else from the frame it came from — state snapshots, timestamps, frame index, device identity — so the output recording plays back like the input with only its points changed:
with VoyantRecorder("edited.vynt", timestamp_filename=False) as recorder:
for frame in playback:
if frame is None:
break
# ... edit `matrix` as above ...
edited = frame.with_points(matrix)
if recorder.record_frame(edited) == RecordStatus.STOP:
break
Command Line Options
python edit_recording_example.py --input recording.vynt --output edited.vynt
# Custom range limit in meters
python edit_recording_example.py --input recording.vynt --output edited.vynt --max-range 25
Expected Output
frame 133: kept 14208/15850 points
frame 134: kept 14197/15873 points
...
Next Steps
- Playback — read back the edited recording
- Edit a Recording (C++) — the same flow with
withPoints() - API Reference — full
VoyantFramereference