Not complete; the object timing infomation comes from gaze tracking, so maybe not totally useful. Also, the general point of this was to output a TextGrid or something similar with these object timings, so it's incomplete in those terms, and can't be until the gaze times are.

datapath = "/Users/joregan/Playing/hsi/"
from pathlib import Path

DATAPATH = Path(datapath)
OBJECT_HEADER = "TimeCode,ObjectName,ObjectPosX,ObjectPosY,ObjectPosZ"
TIMECODE_HEADER = "Frame,Time (Seconds),TimeCode"
def read_timecode(filename):
    header_data = {}
    frame_data = []
    header_line_seen = False
    with open(filename) as inf:
        for line in inf.readlines():
            line = line.strip()
            if line.startswith("Format Version,"):
                header_data = {k[0]: k[1] for k in zip(line.split(",")[0::2], line.split(",")[1::2])}
            if not header_line_seen:
                if line.strip() == TIMECODE_HEADER:
                    header_line_seen = True
                else:
                    continue
            else:
                parts = line.split(",")
                frame_data.append({
                    "frame": parts[0],
                    "abs_time": parts[1],
                    "timecode": parts[2]
                })
    return header_data, frame_data
def read_ojects(filename):
    header_seen = False
    object_codes = []
    with open(filename) as inf:
        for line in inf.readlines():
            line = line.strip()
            if not header_seen:
                if line == OBJECT_HEADER:
                    header_seen = True
                else:
                    continue
            else:
                parts = line.split(",")
                timeparts = parts[0].split(":")
                assert timeparts[3][0] == "0", f"in {filename}: non-zero padded time ({line})"
                timeparts[3] = timeparts[3][1:]
                time = ":".join(timeparts)
                object_codes.append({
                    "timecode": time,
                    "name": parts[1],
                    "x": parts[2],
                    "y": parts[3],
                    "z": parts[4]
                })
    return object_codes
test = read_ojects("/Users/joregan/Playing/hsi/objects/hsi_7_0719_209_002_objects.csv")
import json

def id_to_name(filename):
    fwd = {}
    bck = {}
    with open(filename) as inf:
        data = json.load(inf)
    for child in data["origin"]["children"]:
        bck[child["name"]] = child["unique_id"]
        fwd[child["unique_id"]] = child["name"]
    return fwd, bck
def unique_object_times(data):
    output = []

    last_tc = ""
    cur = {}
    for i in range(len(data)):
        if data[i]["timecode"] == last_tc:
            cur["names"].add(data[i]["name"])
        else:
            if cur != {}:
                output.append(cur)
            cur = {}
            cur["timecode"] = data[i]["timecode"]
            cur["names"] = set()
            cur["names"].add(data[i]["name"])
        last_tc = data[i]["timecode"]
    return output
uniq = unique_object_times(test)
def object_window(data, span=5):
    allcounts = []
    def prcnt():
        out = {}
        for count in counts:
            out[count] = counts[count] / 5
        return out

    for i in range(len(data) - (span - 1)):
        window = data[i:i+5]
        counts = {}
        id_to_set = {}
        timecodes = []
        for item in window:
            timecodes.append(item["timecode"])
            set_id = "__".join(item["names"]) if len(item["names"]) != 1 else list(item["names"])[0]
            if not set_id in counts:
                counts[set_id] = 1
                id_to_set[set_id] = item["names"]
            else:
                counts[set_id] += 1
    
        countspct = prcnt()
        stable = (len(counts) == 1)
        allcounts.append({
            "stable": stable,
            "items": countspct,
            "timecodes": timecodes
        })
    return allcounts
wd = object_window(uniq)
def merge_stable(data):
    to_del = []
    i = 0
    j = 1
    while j < len(data):
        if data[i]["stable"] and data[j]["stable"]:
            data[i]["timecodes"].append(data[j]["timecodes"][-1])
            to_del.append(j)
            j += 1
        else:
            i = j
            j += 1
    for k in reversed(to_del):
        del(data[k])
    return data
merge_stable(wd)[0:3]
[{'stable': True,
  'items': {'HousePlant_8110ba59': 1.0},
  'timecodes': ['18:34:53:02.04',
   '18:34:53:03.04',
   '18:34:53:04.01',
   '18:34:53:04.05',
   '18:34:53:05.01',
   '18:34:53:05.06',
   '18:34:53:06.07',
   '18:34:53:07.07',
   '18:34:53:08.07',
   '18:34:53:09.05',
   '18:34:53:10.03',
   '18:34:53:11.00']},
 {'stable': False,
  'items': {'HousePlant_8110ba59': 0.8,
   'Vase_75ce7b48__Dresser_29dd319f': 0.2},
  'timecodes': ['18:34:53:08.07',
   '18:34:53:09.05',
   '18:34:53:10.03',
   '18:34:53:11.00',
   '18:34:53:12.02']},
 {'stable': False,
  'items': {'HousePlant_8110ba59': 0.6,
   'Vase_75ce7b48__Dresser_29dd319f': 0.2,
   'Vase_75ce7b48': 0.2},
  'timecodes': ['18:34:53:09.05',
   '18:34:53:10.03',
   '18:34:53:11.00',
   '18:34:53:12.02',
   '18:34:53:12.06']}]