The Azure Kinect playback API

The sensor SDK provides an API for recording device data to a Matroska (.mkv) file. The Matroska container format stores video tracks, IMU samples, and device calibration. Recordings can be generated using the provided k4arecorder command-line utility. Recordings can also be customized and recorded directly using the record API.

For more information about the recording API, see k4a_record_create().

For more information on the Matroska file format specifications, see the Recording File Format page.

Use the playback API

Recording files can be opened using the playback API. The playback API provides access to sensor data in the same format as the rest of the sensor SDK.

Open a record file

In the following example, we open a recording using k4a_playback_open(), print the recording length, and then close the file with k4a_playback_close().

k4a_playback_t playback_handle = NULL;
if (k4a_playback_open("recording.mkv", &playback_handle) != K4A_RESULT_SUCCEEDED)
{
    printf("Failed to open recording\n");
    return 1;
}

uint64_t recording_length = k4a_playback_get_last_timestamp_usec(playback_handle);
printf("Recording is %lld seconds long\n", recording_length / 1000000);

k4a_playback_close(playback_handle);

Read captures

Once the file is open, we can start reading captures from the recording. This next example will read each of the captures in the file.

k4a_capture_t capture = NULL;
k4a_stream_result_t result = K4A_STREAM_RESULT_SUCCEEDED;
while (result == K4A_STREAM_RESULT_SUCCEEDED)
{
    result = k4a_playback_get_next_capture(playback_handle, &capture);
    if (result == K4A_STREAM_RESULT_SUCCEEDED)
    {
        // Process capture here
        k4a_capture_release(capture);
    }
    else if (result == K4A_STREAM_RESULT_EOF)
    {
        // End of file reached
        break;
    }
}
if (result == K4A_STREAM_RESULT_FAILED)
{
    printf("Failed to read entire recording\n");
    return 1;
}

Seek within a recording

Once we've reached the end of the file, we may want to go back and read it again. This process could be done by reading backwards with k4a_playback_get_previous_capture(), but it could be very slow depending on the length of the recording. Instead we can use the k4a_playback_seek_timestamp() function to go to a specific point in the file.

In this example, we specify timestamps in microseconds to seek to various points in the file.

// Seek to the beginning of the file
if (k4a_playback_seek_timestamp(playback_handle, 0, K4A_PLAYBACK_SEEK_BEGIN) != K4A_RESULT_SUCCEEDED)
{
    return 1;
}

// Seek to the end of the file
if (k4a_playback_seek_timestamp(playback_handle, 0, K4A_PLAYBACK_SEEK_END) != K4A_RESULT_SUCCEEDED)
{
    return 1;
}

// Seek to 10 seconds from the start
if (k4a_playback_seek_timestamp(playback_handle, 10 * 1000000, K4A_PLAYBACK_SEEK_BEGIN) != K4A_RESULT_SUCCEEDED)
{
    return 1;
}

// Seek to 10 seconds from the end
if (k4a_playback_seek_timestamp(playback_handle, -10 * 1000000, K4A_PLAYBACK_SEEK_END) != K4A_RESULT_SUCCEEDED)
{
    return 1;
}

Read tag information

Recordings can also contain various metadata such as the device serial number and firmware versions. This metadata is stored in recording tags, which can be accessed using the k4a_playback_get_tag() function.

// Print the serial number of the device used to record
char serial_number[256];
size_t serial_number_size = 256;
k4a_buffer_result_t buffer_result = k4a_playback_get_tag(playback_handle, "K4A_DEVICE_SERIAL_NUMBER", &serial_number, &serial_number_size);
if (buffer_result == K4A_BUFFER_RESULT_SUCCEEDED)
{
    printf("Device serial number: %s\n", serial_number);
}
else if (buffer_result == K4A_BUFFER_RESULT_TOO_SMALL)
{
    printf("Device serial number too long.\n");
}
else
{
    printf("Tag does not exist. Device serial number was not recorded.\n");
}

Record tag list

Below is a list of all the default tags that may be included in a recording file. Many of these values are available as part of the k4a_record_configuration_t struct, and can be read with the k4a_playback_get_record_configuration() function.

If a tag doesn't exist, it's assumed to have the default value.

Tag Name Default Value k4a_record_configuration_t Field Notes
K4A_COLOR_MODE "OFF" color_format / color_resolution Possible values: "OFF", "MJPG_1080P", "NV12_720P", "YUY2_720P", and so on
K4A_DEPTH_MODE "OFF" depth_mode / depth_track_enabled Possible values: "OFF, "NFOV_UNBINNED", "PASSIVE_IR", and so on
K4A_IR_MODE "OFF" depth_mode / ir_track_enabled Possible values: "OFF", "ACTIVE", "PASSIVE"
K4A_IMU_MODE "OFF" imu_track_enabled Possible values: "ON", "OFF"
K4A_CALIBRATION_FILE "calibration.json" N/A See k4a_device_get_raw_calibration()
K4A_DEPTH_DELAY_NS "0" depth_delay_off_color_usec Value stored in nanoseconds, API provides microseconds.
K4A_WIRED_SYNC_MODE "STANDALONE" wired_sync_mode Possible values: "STANDALONE", "MASTER", "SUBORDINATE"
K4A_SUBORDINATE_DELAY_NS "0" subordinate_delay_off_master_usec Value stored in nanoseconds, API provides microseconds.
K4A_COLOR_FIRMWARE_VERSION "" N/A Device color firmware version, for example "1.x.xx"
K4A_DEPTH_FIRMWARE_VERSION "" N/A Device depth firmware version, for example "1.x.xx"
K4A_DEVICE_SERIAL_NUMBER "" N/A Recording device serial number
K4A_START_OFFSET_NS "0" start_timestamp_offset_usec See Timestamp Synchronization below.
K4A_COLOR_TRACK None N/A See Recording File Format - Identifying tracks.
K4A_DEPTH_TRACK None N/A See Recording File Format - Identifying tracks.
K4A_IR_TRACK None N/A See Recording File Format - Identifying tracks.
K4A_IMU_TRACK None N/A See Recording File Format - Identifying tracks.

Timestamp synchronization

The Matroska format requires that recordings must start with a timestamp of zero. When externally syncing cameras, the first timestamp from of each device can be non-zero.

To preserve the original timestamps from the devices between recording and playback, the file stores an offset to apply to the timestamps.

The K4A_START_OFFSET_NS tag is used to specify a timestamp offset so that files can be resynchronized after recording. This timestamp offset can be added to each timestamp in the file to reconstruct the original device timestamps.

The start offset is also available in the k4a_record_configuration_t struct.