> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nomadicml.com/llms.txt
> Use this file to discover all available pages before exploring further.

# What is Dataset Studio?

> Know exactly what is in your footage — and what is missing

Fleets record far more video than anyone can watch. The hard question is rarely
"do we have data?" but **"do we have enough of the right scenarios?"** Night
rain with pedestrians. Unprotected left turns. Faded lane lines on a curve.

Dataset Studio turns Nomadic's analysis of your videos into a dataset you can
search, slice and count, so you can answer that question in minutes instead of
weeks of manual review.

<CardGroup cols={3}>
  <Card title="Find" icon="magnifying-glass">
    Search every event in plain language: *"hard brake for a cut-in"*.
  </Card>

  <Card title="Measure" icon="chart-simple">
    See how events spread across weather, lighting, maneuver and any field you define.
  </Card>

  <Card title="Close gaps" icon="bullseye">
    List the scenario combinations you are short on, then go collect them.
  </Card>
</CardGroup>

## From raw footage to coverage

Nomadic watches your videos and returns **events**, each tagged with the fields
you asked for. Dataset Studio collects those events into one place, so a
question about thousands of clips becomes a filter and a count.

<div style={{ border: '1px solid rgba(127,127,127,0.25)', borderRadius: '16px', padding: '20px', margin: '24px 0' }}>
  <div style={{ display: 'flex', flexWrap: 'wrap', alignItems: 'stretch', gap: '8px' }}>
    <div style={{ flex: '1 1 120px', border: '1px solid rgba(127,127,127,0.3)', borderRadius: '12px', padding: '12px 14px' }}>
      <div style={{ fontSize: '11px', fontWeight: 700, letterSpacing: '0.06em', color: '#3E48CC' }}>01</div>
      <div style={{ fontWeight: 600, marginTop: '4px' }}>Videos</div>
      <div style={{ fontSize: '13px', opacity: 0.7, marginTop: '2px' }}>Fleet uploads, folders, cloud buckets</div>
    </div>

    <div style={{ alignSelf: 'center', opacity: 0.4, fontSize: '18px' }}>→</div>

    <div style={{ flex: '1 1 120px', border: '1px solid rgba(127,127,127,0.3)', borderRadius: '12px', padding: '12px 14px' }}>
      <div style={{ fontSize: '11px', fontWeight: 700, letterSpacing: '0.06em', color: '#3E48CC' }}>02</div>
      <div style={{ fontWeight: 600, marginTop: '4px' }}>Analysis</div>
      <div style={{ fontSize: '13px', opacity: 0.7, marginTop: '2px' }}>Nomadic finds the moments you asked for</div>
    </div>

    <div style={{ alignSelf: 'center', opacity: 0.4, fontSize: '18px' }}>→</div>

    <div style={{ flex: '1 1 120px', border: '1px solid rgba(127,127,127,0.3)', borderRadius: '12px', padding: '12px 14px' }}>
      <div style={{ fontSize: '11px', fontWeight: 700, letterSpacing: '0.06em', color: '#3E48CC' }}>03</div>
      <div style={{ fontWeight: 600, marginTop: '4px' }}>Labeled events</div>
      <div style={{ fontSize: '13px', opacity: 0.7, marginTop: '2px' }}>Each tagged: weather, lighting, maneuver</div>
    </div>

    <div style={{ alignSelf: 'center', opacity: 0.4, fontSize: '18px' }}>→</div>

    <div style={{ flex: '1 1 120px', borderRadius: '12px', padding: '12px 14px', background: '#3E48CC', color: '#ffffff' }}>
      <div style={{ fontSize: '11px', fontWeight: 700, letterSpacing: '0.06em', opacity: 0.8 }}>04</div>
      <div style={{ fontWeight: 600, marginTop: '4px' }}>Dataset Studio</div>
      <div style={{ fontSize: '13px', opacity: 0.85, marginTop: '2px' }}>Search, slice and count every event</div>
    </div>
  </div>

  <div style={{ display: 'flex', flexWrap: 'wrap', gap: '8px', marginTop: '14px', paddingTop: '14px', borderTop: '1px dashed rgba(127,127,127,0.3)', alignItems: 'center', fontSize: '13px' }}>
    <span style={{ fontWeight: 600, marginRight: '4px' }}>You get</span>
    <span style={{ border: '1px solid rgba(62,72,204,0.45)', color: '#3E48CC', borderRadius: '999px', padding: '3px 10px', fontWeight: 600 }}>Explore</span>
    <span style={{ border: '1px solid rgba(62,72,204,0.45)', color: '#3E48CC', borderRadius: '999px', padding: '3px 10px', fontWeight: 600 }}>Distribution</span>
    <span style={{ border: '1px solid rgba(62,72,204,0.45)', color: '#3E48CC', borderRadius: '999px', padding: '3px 10px', fontWeight: 600 }}>Coverage gaps</span>
    <span style={{ marginLeft: 'auto', opacity: 0.7 }}>↺ Gaps tell you what to collect or analyze next</span>
  </div>
</div>

That loop is the point. Studio tells you what to collect or analyze next, and
each new batch slots into the same dataset.

## Four ideas to know

<CardGroup cols={2}>
  <Card title="Analysis batch" icon="film">
    **One analysis run over many videos.** It finds the moments that match your
    prompt, such as *"identify road scenes"*, and produces events.
  </Card>

  <Card title="Event" icon="clock">
    **A labeled moment in a video.** A start and end time, a description and the
    field values that describe it, such as `weather: rain`.
  </Card>

  <Card title="Taxonomy" icon="tags">
    **The fields you classify by.** Weather, lighting, lane type: each becomes a
    filter in the app and a column in your coverage table.
  </Card>

  <Card title="Studio dataset" icon="database">
    **Your browsable dataset.** It groups events from one or more batches or
    folders and keeps its taxonomies with it.
  </Card>
</CardGroup>

Here is how they connect:

<div style={{ border: '1px solid rgba(127,127,127,0.25)', borderRadius: '16px', padding: '20px', margin: '24px 0' }}>
  <div style={{ display: 'flex', flexWrap: 'wrap', alignItems: 'center', justifyContent: 'space-between', gap: '8px' }}>
    <div>
      <div style={{ fontSize: '11px', fontWeight: 700, letterSpacing: '0.06em', opacity: 0.6 }}>STUDIO DATASET</div>
      <div style={{ fontWeight: 600 }}>Road scenes Q3</div>
    </div>

    <div style={{ background: '#3E48CC', color: '#ffffff', borderRadius: '10px', padding: '6px 12px', fontSize: '13px' }}>
      <span style={{ fontWeight: 700 }}>Taxonomy</span> · weather · lighting
    </div>
  </div>

  <div style={{ display: 'flex', flexWrap: 'wrap', gap: '12px', marginTop: '16px' }}>
    <div style={{ flex: '1 1 220px', border: '1px solid rgba(127,127,127,0.3)', borderRadius: '12px', padding: '12px' }}>
      <div style={{ fontSize: '12px', fontWeight: 600, opacity: 0.7, marginBottom: '8px' }}>Bucket · events from Batch A</div>

      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: '8px', border: '1px solid rgba(127,127,127,0.2)', borderRadius: '8px', padding: '6px 10px', fontSize: '13px', marginBottom: '6px' }}>
        <span>Pedestrian crossing</span>
        <span><code>rain</code> <code>night</code></span>
      </div>

      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: '8px', border: '1px solid rgba(127,127,127,0.2)', borderRadius: '8px', padding: '6px 10px', fontSize: '13px' }}>
        <span>Lane change</span>
        <span><code>clear</code> <code>day</code></span>
      </div>
    </div>

    <div style={{ flex: '1 1 220px', border: '1px solid rgba(127,127,127,0.3)', borderRadius: '12px', padding: '12px' }}>
      <div style={{ fontSize: '12px', fontWeight: 600, opacity: 0.7, marginBottom: '8px' }}>Bucket · events from Batch B</div>

      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: '8px', border: '1px solid rgba(127,127,127,0.2)', borderRadius: '8px', padding: '6px 10px', fontSize: '13px', marginBottom: '6px' }}>
        <span>Hard brake</span>
        <span><code>fog</code> <code>twilight</code></span>
      </div>

      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: '8px', border: '1px solid rgba(127,127,127,0.2)', borderRadius: '8px', padding: '6px 10px', fontSize: '13px' }}>
        <span>Unprotected left turn</span>
        <span><code>rain</code> <code>day</code></span>
      </div>
    </div>
  </div>

  <div style={{ fontSize: '13px', opacity: 0.7, marginTop: '12px' }}>
    Every event gets a value for each taxonomy field, so the whole dataset can be filtered and counted by them.
  </div>
</div>

<Tip>
  If a batch ran with [Structured Output](/sdk/structured-output), its schema
  **becomes the Studio's taxonomy** automatically. The events are already
  classified, so there is no second analysis to wait for.
</Tip>

## Three steps

<Steps>
  <Step title="Define what you care about">
    Describe your fields once, as a schema. They guide the analysis and become
    your taxonomy.

    ```python theme={null}
    class RoadScene(BaseModel):
        weather: Literal["clear", "rain", "snow", "fog"]
        lighting: Literal["day", "night", "twilight"]

    batch = client.analyze(
        video_ids,
        "Identify road scenes.",
        output_schema=RoadScene,
    )
    ```
  </Step>

  <Step title="Create a Studio">
    Turn the finished batch into a dataset. Open `studio.url` to browse it in the
    app, or use **Create Studio** from the batch viewer.

    ```python theme={null}
    studio = client.studio.create_from_batch(
        batch,
        title="Road scenes Q3",
    )
    ```
  </Step>

  <Step title="Find your gaps">
    Get every combination of field values with its event count. Combinations
    with no examples are missing from the table.

    ```python theme={null}
    coverage = client.studio.coverage(studio.id)
    coverage[coverage.events < 20]  # the scenarios you are short on
    ```
  </Step>
</Steps>

## See your coverage at a glance

Coverage is the core of Studio. Here is an illustrative weather × lighting
breakdown for the `RoadScene` schema above:

<div style={{ border: '1px solid rgba(127,127,127,0.25)', borderRadius: '16px', padding: '20px', margin: '24px 0', overflowX: 'auto' }}>
  <div style={{ display: 'grid', gridTemplateColumns: '72px repeat(3, minmax(80px, 1fr))', gap: '6px', fontSize: '13px', minWidth: '340px' }}>
    <div />

    <div style={{ textAlign: 'center', fontWeight: 600, opacity: 0.7 }}>day</div>
    <div style={{ textAlign: 'center', fontWeight: 600, opacity: 0.7 }}>twilight</div>
    <div style={{ textAlign: 'center', fontWeight: 600, opacity: 0.7 }}>night</div>
    <div style={{ alignSelf: 'center', fontWeight: 600, opacity: 0.7 }}>clear</div>
    <div style={{ background: '#3E48CC', color: '#fff', borderRadius: '8px', padding: '10px', textAlign: 'center', fontWeight: 600 }}>1,284</div>
    <div style={{ background: '#3E48CC', color: '#fff', borderRadius: '8px', padding: '10px', textAlign: 'center', fontWeight: 600 }}>310</div>
    <div style={{ background: '#3E48CC', color: '#fff', borderRadius: '8px', padding: '10px', textAlign: 'center', fontWeight: 600 }}>642</div>
    <div style={{ alignSelf: 'center', fontWeight: 600, opacity: 0.7 }}>rain</div>
    <div style={{ background: '#3E48CC', color: '#fff', borderRadius: '8px', padding: '10px', textAlign: 'center', fontWeight: 600 }}>233</div>
    <div style={{ background: 'rgba(62,72,204,0.35)', borderRadius: '8px', padding: '10px', textAlign: 'center', fontWeight: 600 }}>61</div>
    <div style={{ background: 'rgba(245,158,11,0.22)', border: '1px solid rgba(245,158,11,0.6)', borderRadius: '8px', padding: '10px', textAlign: 'center', fontWeight: 600 }}>14</div>
    <div style={{ alignSelf: 'center', fontWeight: 600, opacity: 0.7 }}>snow</div>
    <div style={{ background: 'rgba(62,72,204,0.35)', borderRadius: '8px', padding: '10px', textAlign: 'center', fontWeight: 600 }}>96</div>
    <div style={{ border: '1px dashed rgba(239,68,68,0.7)', color: 'rgb(239,68,68)', borderRadius: '8px', padding: '10px', textAlign: 'center', fontWeight: 600 }}>gap</div>
    <div style={{ background: 'rgba(245,158,11,0.22)', border: '1px solid rgba(245,158,11,0.6)', borderRadius: '8px', padding: '10px', textAlign: 'center', fontWeight: 600 }}>8</div>
    <div style={{ alignSelf: 'center', fontWeight: 600, opacity: 0.7 }}>fog</div>
    <div style={{ background: 'rgba(62,72,204,0.35)', borderRadius: '8px', padding: '10px', textAlign: 'center', fontWeight: 600 }}>52</div>
    <div style={{ background: 'rgba(245,158,11,0.22)', border: '1px solid rgba(245,158,11,0.6)', borderRadius: '8px', padding: '10px', textAlign: 'center', fontWeight: 600 }}>11</div>
    <div style={{ border: '1px dashed rgba(239,68,68,0.7)', color: 'rgb(239,68,68)', borderRadius: '8px', padding: '10px', textAlign: 'center', fontWeight: 600 }}>gap</div>
  </div>

  <div style={{ display: 'flex', flexWrap: 'wrap', gap: '16px', marginTop: '14px', fontSize: '12px', opacity: 0.8 }}>
    <span><span style={{ display: 'inline-block', width: '10px', height: '10px', borderRadius: '3px', background: '#3E48CC', marginRight: '6px' }} />Deep, 200+ events</span>
    <span><span style={{ display: 'inline-block', width: '10px', height: '10px', borderRadius: '3px', background: 'rgba(62,72,204,0.35)', marginRight: '6px' }} />Usable</span>
    <span><span style={{ display: 'inline-block', width: '10px', height: '10px', borderRadius: '3px', background: 'rgba(245,158,11,0.5)', marginRight: '6px' }} />Thin, under 20</span>
    <span><span style={{ display: 'inline-block', width: '10px', height: '10px', borderRadius: '3px', border: '1px dashed rgb(239,68,68)', marginRight: '6px' }} />No examples</span>
  </div>
</div>

In seconds you can see the data is deep on clear days, thin on rainy nights
and has nothing for snowy twilight or foggy nights. That is what you need to
plan the next collection run, balance a training set or show that an
evaluation covers the conditions it claims to.

`coverage()` returns the same information as a table with one row per
combination. Combinations with no examples are left out, so a gap is a row
that is not there.

## In the app

<CardGroup cols={3}>
  <Card title="Explore" icon="compass">
    Browse and play event clips. Search in plain language and filter by any
    taxonomy field.
  </Card>

  <Card title="Distribution" icon="chart-column">
    See how many events fall under each value and how the dataset is balanced.
  </Card>

  <Card title="Taxonomy" icon="sitemap">
    Review your fields and add new ones. New fields are classified over the
    whole dataset.
  </Card>
</CardGroup>

## Start here

<CardGroup cols={2}>
  <Card title="Define fields" icon="list-check" href="/sdk/structured-output">
    Run an analysis that returns typed fields.
  </Card>

  <Card title="Create a Studio" icon="database" href="/sdk/create-studio">
    Build a dataset from batches or folders.
  </Card>

  <Card title="Add taxonomies and coverage" icon="table-cells" href="/sdk/studio">
    Classify by new fields and read the full coverage table.
  </Card>

  <Card title="Set up the SDK" icon="code" href="/sdk/sdk_installation">
    Install the SDK and connect with an API key.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.