Skip to main content

Video Recorder (beta)

Allows you to define Tracks that will be continuously recorded from the video sources you select. The tracks are recorded in segments and these segments are uploaded to the cloud if and when desired. By default all segments are uploaded right away. This can be controlled dynamically on the robot via the API exposed by the capability on the robot described below.

Supports the same video sources as WebRTC Video, incl. v4l cameras, rtsp streams, ROS topics, as well as arbitrary custom gstreamer source pielines.

The capability provides a web UI from where available recordings can be played and reviewed. A calendar UI shows for which days and times recordings are available.

Robot API

The API on the robot is current available via ROS topics:

  • /transitive/video_recorder/keep is a number indicating how many seconds back from the current time segments should be uploaded to the cloud. The default is 0 which means new segments should be uploaded, but past segments that may not have been uploaded yet should be ignored. Set to -1 to indicate no upload at all (until changed), i.e., to indicate that the currently gathered video segments are not interesting enough to upload. These segments will still be available on the robot until the retention period is reached (currently one hour).
  • /transitive/video_recorder/idle indicates whether the robot is currently idle and ready to upload video segments to the cloud. The default is true. When set to false, upload will be paused. Any segments that are marked to be kept will be gathered during this time and uploaded once the robot is marked as idle again.

Front-end (web) API

On the front-end, i.e., in the browser, the capability provides a simple API for getting the available recordings:

async getRecordings({
start: Number, // e.g., 1748908800000
end: Number, // e.g., 1748995200000
})

This will fetch all the recordings between start and end, both of which are times specified in milliseconds since the epoch, i.e., like Date.now(). If the duration between start and end is less than a day, then the result will be a list of recordings for that day. Otherwise the result will be a list of days and the tracks for which there exists recordings on those days.

Example

import { CapabilityContext, CapabilityContextProvider }
from '@transitive-sdk/utils-web';

const ShowRecordings = ({jwt}) => {
const context = useContext(CapabilityContext);
context.getRecordings({start: 1748908800000, end: 1748995200000}).then(console.log);
};

const MyComponent = ({jwt}) =>
<CapabilityContextProvider jwt={jwt}>
<ShowRecordings />
</CapabilityContextProvider>;

Device Sharing

In order to allow other processes to use the input devices used by the video recorder, e.g., for video-streaming or CV processing, the Video Recorder capability "tee"s the stream and exposes the shared stream via shared memory from where it can be consumed by other processes. The file location of the shared memory is /tmp/.transitive-video-recorder/shm/TRACK_NAME.

Example

For instance, if there is an active video recorder running named "ForwardCamera" then this camera feed could still be used in Transitive's Remote Teleop capability using a custom source pipeline as follows:

<remote-teleop-device id="superbots"
jwt="eyJh...."
count="1"
type="custom"
source="shmsrc is-live=true socket-path=/tmp/.transitive-video-recorder/shm/ForwardCamera do-timestamp=true ! application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)JPEG ! rtpjpegdepay ! jpegdec ! videoconvert"
/>

In the near future we will automatically detect these shared sources in these other capabilities and make them available in the sources menu.

Details
Version 0.1.3, published 6/19/2025, 5:41:58 PM
$20/robot/month