Ex: Edit a Recording
Filter or modify a recording’s points and save the result with C++.
This example edits a Voyant recording and saves it back: read each frame, filter or modify its points, rebuild the frame with withPoints(), 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.
What You’ll Learn
- How to chain
VoyantPlaybackintoVoyantRecorderto rewrite a recording - How to rebuild a frame with edited points using
withPoints() - How to stamp the user-owned per-point bytes (
user_data)
Prerequisites
- Voyant SDK installed (see Installation)
- 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.cpp
Key Concepts
Reader and Writer
Playback is the reader and the recorder is the writer. Rate 0 replays as fast as possible; with keep_invalid_points left false, invalid returns are dropped as frames are read, so the output holds only valid points:
VoyantPlayback player(0.0, false, false);
player.openFile(inputPath);
VoyantRecorderConfig config(outputPath);
config.timestampFilename = false;
VoyantRecorder recorder(config);
Editing the Points
Any per-point edit works. This one keeps points within a range limit and stamps the user-owned bytes to mark the points the program touched — the visualizer’s User Data color mode can then highlight them:
std::vector<PointData> kept;
kept.reserve(frame.nPoints());
for (const PointData& point : frame.points())
{
if (point.range_m <= maxRangeM)
{
kept.push_back(point);
kept.back().user_data[0] = 1;
}
}
Points that arrive as x/y/z — from a ROS cloud, a CSV — go in through setPointsXyz(), the inverse of VoyantFrame::xyz(). It writes the positions into the points’ stored spherical geometry, so fill the rest of each point first and let the library own the projection rather than rebuilding the angles by hand:
std::vector<VoyantVec3> positions = /* x, y, z from your source */;
// false if the two lengths differ; a non-finite or zero-length position stores as range 0
setPointsXyz(kept, positions);
Rebuilding and Recording the Frame
withPoints() 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:
while (player.nextFrame())
{
const VoyantFrame& frame = player.currentFrame();
// ... build `kept` as above ...
VoyantFrame edited = frame.withPoints(std::move(kept));
RecordResult result = recorder.recordFrame(edited);
}
recorder.finalize();
RecordResult::Finished is not an error — a configured limit was reached, so stop feeding the recorder; finalize() still closes the file.
Building and Running
# Build the examples
mkdir build && cd build
cmake ..
make
# Keep points within 50 m (the default) and write the result
./bin/edit_recording_example input.vynt output.vynt
# Custom range limit in meters
./bin/edit_recording_example input.vynt output.vynt 25
Expected Output
frame 133: kept 14208/15850 points
frame 134: kept 14197/15873 points
...
Wrote output.vynt
Next Steps
- Playback — read back the edited recording
- Edit a Recording (Python) — the same flow with
frame.with_points()on thepoints()matrix - API Documentation — full
VoyantFramereference