{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "d892408c",
   "metadata": {},
   "source": [
    "# 2 - Record a dataset and stream it back\n",
    "\n",
    "Capture a robot demonstration as a [LeRobotDataset](https://github.com/huggingface/lerobot), then read it back frame by frame with `stream_dataset()` - the in-process counterpart to recording. Camera video decodes on the fly; nothing is re-materialized to disk.\n",
    "\n",
    "No hardware, no GPU, no Hugging Face credentials. Part of the [examples/notebooks](./README.md) series; see [notebook 1](./01_getting_started.ipynb) first."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4d8be70a",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-06-29T14:28:06.809884Z",
     "iopub.status.busy": "2026-06-29T14:28:06.809801Z",
     "iopub.status.idle": "2026-06-29T14:28:06.813260Z",
     "shell.execute_reply": "2026-06-29T14:28:06.812803Z"
    }
   },
   "outputs": [],
   "source": [
    "import os\n",
    "import sys\n",
    "\n",
    "# macOS uses the 'cgl' offscreen GL backend; Linux headless uses 'egl'.\n",
    "os.environ.setdefault(\"MUJOCO_GL\", \"cgl\" if sys.platform == \"darwin\" else \"egl\")\n",
    "\n",
    "ROOT, REPO = \"/tmp/nb2_dataset\", \"local/nb2_demo\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b5d053c9",
   "metadata": {},
   "source": [
    "## Record\n",
    "\n",
    "`start_recording()` opens a `LeRobotDataset`, the policy loop fills it frame by frame, and `stop_recording()` finalizes it (encoding per-camera MP4 and writing the `meta/` folder of stats and schema). A camera is added first so the recorded dataset has an image stream."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "68b1eca9",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-06-29T14:28:06.814599Z",
     "iopub.status.busy": "2026-06-29T14:28:06.814530Z",
     "iopub.status.idle": "2026-06-29T14:28:15.941996Z",
     "shell.execute_reply": "2026-06-29T14:28:15.941566Z"
    }
   },
   "outputs": [],
   "source": [
    "from strands_robots import MockPolicy, Robot\n",
    "\n",
    "sim = Robot(\"so100\", mesh=False)\n",
    "sim.add_camera(name=\"front\", position=[0.5, 0.0, 0.4], target=[0.2, 0.0, 0.05])\n",
    "\n",
    "sim.start_recording(repo_id=REPO, root=ROOT, fps=30, task=\"pick up the red cube\", overwrite=True)\n",
    "sim.run_policy(robot_name=\"so100\", policy_object=MockPolicy(), instruction=\"pick up the red cube\", n_steps=60)\n",
    "sim.stop_recording()\n",
    "print(\"recorded ->\", ROOT)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "89f25da9",
   "metadata": {},
   "source": [
    "## Stream it back\n",
    "\n",
    "`stream_dataset()` reads the dataset you just wrote. Iterating yields one frame at a time: the joint state and action come from the Parquet shards, and camera frames decode from the MP4 shards as you go. Only the small `meta/` folder is read up front."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dc4e5a4f",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-06-29T14:28:15.943456Z",
     "iopub.status.busy": "2026-06-29T14:28:15.943290Z",
     "iopub.status.idle": "2026-06-29T14:28:16.504988Z",
     "shell.execute_reply": "2026-06-29T14:28:16.504582Z"
    }
   },
   "outputs": [],
   "source": [
    "reader = sim.stream_dataset(REPO, root=ROOT, shuffle=False)\n",
    "print(\"episodes:\", reader.num_episodes, \"| frames:\", reader.num_frames, \"| fps:\", reader.fps)\n",
    "\n",
    "for n, frame in enumerate(reader):\n",
    "    if n == 0:\n",
    "        cams = [k for k in frame if k.startswith(\"observation.images.\")]\n",
    "        print(\n",
    "            \"state:\",\n",
    "            tuple(frame[\"observation.state\"].shape),\n",
    "            \"| action:\",\n",
    "            tuple(frame[\"action\"].shape),\n",
    "            \"| cameras:\",\n",
    "            cams,\n",
    "        )\n",
    "    if n >= 4:\n",
    "        break\n",
    "print(\"streamed frames OK - nothing re-downloaded\")\n",
    "sim.destroy()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "39636a98",
   "metadata": {},
   "source": [
    "## Why this matters\n",
    "\n",
    "The same `Robot()` that wrote the dataset reads it back, so collecting data and consuming it are two methods on one object in one format. For training at scale, hand the reader a `DataLoader` (`reader.dataloader(batch_size=64)`); for storing collection runs, `stop_recording(bucket=\"org/name\")` syncs to a Hugging Face Storage Bucket.\n",
    "\n",
    "## Next\n",
    "\n",
    "**[3 - Record, train, deploy](./03_record_train_deploy.ipynb)** trains a policy on a dataset like this one."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.12"
  },
  "widgets": {
   "application/vnd.jupyter.widget-state+json": {
    "state": {
     "0c8087d335804739a53b5d5b2c45d57f": {
      "model_module": "@jupyter-widgets/controls",
      "model_module_version": "2.0.0",
      "model_name": "HTMLModel",
      "state": {
       "_dom_classes": [],
       "_model_module": "@jupyter-widgets/controls",
       "_model_module_version": "2.0.0",
       "_model_name": "HTMLModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/controls",
       "_view_module_version": "2.0.0",
       "_view_name": "HTMLView",
       "description": "",
       "description_allow_html": false,
       "layout": "IPY_MODEL_f1b16f3e2ae34978bb5db7bff19cb031",
       "placeholder": "​",
       "style": "IPY_MODEL_11dd2fb41ab549a3a89d58b454d9bcce",
       "tabbable": null,
       "tooltip": null,
       "value": "Map: 100%"
      }
     },
     "11dd2fb41ab549a3a89d58b454d9bcce": {
      "model_module": "@jupyter-widgets/controls",
      "model_module_version": "2.0.0",
      "model_name": "HTMLStyleModel",
      "state": {
       "_model_module": "@jupyter-widgets/controls",
       "_model_module_version": "2.0.0",
       "_model_name": "HTMLStyleModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/base",
       "_view_module_version": "2.0.0",
       "_view_name": "StyleView",
       "background": null,
       "description_width": "",
       "font_size": null,
       "text_color": null
      }
     },
     "174f1aefeab54502ba7b70b89ac5bca3": {
      "model_module": "@jupyter-widgets/controls",
      "model_module_version": "2.0.0",
      "model_name": "FloatProgressModel",
      "state": {
       "_dom_classes": [],
       "_model_module": "@jupyter-widgets/controls",
       "_model_module_version": "2.0.0",
       "_model_name": "FloatProgressModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/controls",
       "_view_module_version": "2.0.0",
       "_view_name": "ProgressView",
       "bar_style": "success",
       "description": "",
       "description_allow_html": false,
       "layout": "IPY_MODEL_3bb990ecfcc94fca9b8e474615c81592",
       "max": 60.0,
       "min": 0.0,
       "orientation": "horizontal",
       "style": "IPY_MODEL_6a83e2eeef88496a80b8ba91a0a5a969",
       "tabbable": null,
       "tooltip": null,
       "value": 60.0
      }
     },
     "359038edc86e408e85cd42166619cb30": {
      "model_module": "@jupyter-widgets/controls",
      "model_module_version": "2.0.0",
      "model_name": "HBoxModel",
      "state": {
       "_dom_classes": [],
       "_model_module": "@jupyter-widgets/controls",
       "_model_module_version": "2.0.0",
       "_model_name": "HBoxModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/controls",
       "_view_module_version": "2.0.0",
       "_view_name": "HBoxView",
       "box_style": "",
       "children": [
        "IPY_MODEL_0c8087d335804739a53b5d5b2c45d57f",
        "IPY_MODEL_174f1aefeab54502ba7b70b89ac5bca3",
        "IPY_MODEL_a014bb0bfe1847dea7a7eff66e7e8966"
       ],
       "layout": "IPY_MODEL_8823f2c757d64c52864a0805f11a2b87",
       "tabbable": null,
       "tooltip": null
      }
     },
     "3bb990ecfcc94fca9b8e474615c81592": {
      "model_module": "@jupyter-widgets/base",
      "model_module_version": "2.0.0",
      "model_name": "LayoutModel",
      "state": {
       "_model_module": "@jupyter-widgets/base",
       "_model_module_version": "2.0.0",
       "_model_name": "LayoutModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/base",
       "_view_module_version": "2.0.0",
       "_view_name": "LayoutView",
       "align_content": null,
       "align_items": null,
       "align_self": null,
       "border_bottom": null,
       "border_left": null,
       "border_right": null,
       "border_top": null,
       "bottom": null,
       "display": null,
       "flex": null,
       "flex_flow": null,
       "grid_area": null,
       "grid_auto_columns": null,
       "grid_auto_flow": null,
       "grid_auto_rows": null,
       "grid_column": null,
       "grid_gap": null,
       "grid_row": null,
       "grid_template_areas": null,
       "grid_template_columns": null,
       "grid_template_rows": null,
       "height": null,
       "justify_content": null,
       "justify_items": null,
       "left": null,
       "margin": null,
       "max_height": null,
       "max_width": null,
       "min_height": null,
       "min_width": null,
       "object_fit": null,
       "object_position": null,
       "order": null,
       "overflow": null,
       "padding": null,
       "right": null,
       "top": null,
       "visibility": null,
       "width": null
      }
     },
     "6a83e2eeef88496a80b8ba91a0a5a969": {
      "model_module": "@jupyter-widgets/controls",
      "model_module_version": "2.0.0",
      "model_name": "ProgressStyleModel",
      "state": {
       "_model_module": "@jupyter-widgets/controls",
       "_model_module_version": "2.0.0",
       "_model_name": "ProgressStyleModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/base",
       "_view_module_version": "2.0.0",
       "_view_name": "StyleView",
       "bar_color": null,
       "description_width": ""
      }
     },
     "8823f2c757d64c52864a0805f11a2b87": {
      "model_module": "@jupyter-widgets/base",
      "model_module_version": "2.0.0",
      "model_name": "LayoutModel",
      "state": {
       "_model_module": "@jupyter-widgets/base",
       "_model_module_version": "2.0.0",
       "_model_name": "LayoutModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/base",
       "_view_module_version": "2.0.0",
       "_view_name": "LayoutView",
       "align_content": null,
       "align_items": null,
       "align_self": null,
       "border_bottom": null,
       "border_left": null,
       "border_right": null,
       "border_top": null,
       "bottom": null,
       "display": null,
       "flex": null,
       "flex_flow": null,
       "grid_area": null,
       "grid_auto_columns": null,
       "grid_auto_flow": null,
       "grid_auto_rows": null,
       "grid_column": null,
       "grid_gap": null,
       "grid_row": null,
       "grid_template_areas": null,
       "grid_template_columns": null,
       "grid_template_rows": null,
       "height": null,
       "justify_content": null,
       "justify_items": null,
       "left": null,
       "margin": null,
       "max_height": null,
       "max_width": null,
       "min_height": null,
       "min_width": null,
       "object_fit": null,
       "object_position": null,
       "order": null,
       "overflow": null,
       "padding": null,
       "right": null,
       "top": null,
       "visibility": null,
       "width": null
      }
     },
     "a014bb0bfe1847dea7a7eff66e7e8966": {
      "model_module": "@jupyter-widgets/controls",
      "model_module_version": "2.0.0",
      "model_name": "HTMLModel",
      "state": {
       "_dom_classes": [],
       "_model_module": "@jupyter-widgets/controls",
       "_model_module_version": "2.0.0",
       "_model_name": "HTMLModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/controls",
       "_view_module_version": "2.0.0",
       "_view_name": "HTMLView",
       "description": "",
       "description_allow_html": false,
       "layout": "IPY_MODEL_f966457bf5934c31a44c7c7f193c512e",
       "placeholder": "​",
       "style": "IPY_MODEL_fcb820f0030947e8aaae371dc73b01f6",
       "tabbable": null,
       "tooltip": null,
       "value": " 60/60 [00:00&lt;00:00, 3162.25 examples/s]"
      }
     },
     "f1b16f3e2ae34978bb5db7bff19cb031": {
      "model_module": "@jupyter-widgets/base",
      "model_module_version": "2.0.0",
      "model_name": "LayoutModel",
      "state": {
       "_model_module": "@jupyter-widgets/base",
       "_model_module_version": "2.0.0",
       "_model_name": "LayoutModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/base",
       "_view_module_version": "2.0.0",
       "_view_name": "LayoutView",
       "align_content": null,
       "align_items": null,
       "align_self": null,
       "border_bottom": null,
       "border_left": null,
       "border_right": null,
       "border_top": null,
       "bottom": null,
       "display": null,
       "flex": null,
       "flex_flow": null,
       "grid_area": null,
       "grid_auto_columns": null,
       "grid_auto_flow": null,
       "grid_auto_rows": null,
       "grid_column": null,
       "grid_gap": null,
       "grid_row": null,
       "grid_template_areas": null,
       "grid_template_columns": null,
       "grid_template_rows": null,
       "height": null,
       "justify_content": null,
       "justify_items": null,
       "left": null,
       "margin": null,
       "max_height": null,
       "max_width": null,
       "min_height": null,
       "min_width": null,
       "object_fit": null,
       "object_position": null,
       "order": null,
       "overflow": null,
       "padding": null,
       "right": null,
       "top": null,
       "visibility": null,
       "width": null
      }
     },
     "f966457bf5934c31a44c7c7f193c512e": {
      "model_module": "@jupyter-widgets/base",
      "model_module_version": "2.0.0",
      "model_name": "LayoutModel",
      "state": {
       "_model_module": "@jupyter-widgets/base",
       "_model_module_version": "2.0.0",
       "_model_name": "LayoutModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/base",
       "_view_module_version": "2.0.0",
       "_view_name": "LayoutView",
       "align_content": null,
       "align_items": null,
       "align_self": null,
       "border_bottom": null,
       "border_left": null,
       "border_right": null,
       "border_top": null,
       "bottom": null,
       "display": null,
       "flex": null,
       "flex_flow": null,
       "grid_area": null,
       "grid_auto_columns": null,
       "grid_auto_flow": null,
       "grid_auto_rows": null,
       "grid_column": null,
       "grid_gap": null,
       "grid_row": null,
       "grid_template_areas": null,
       "grid_template_columns": null,
       "grid_template_rows": null,
       "height": null,
       "justify_content": null,
       "justify_items": null,
       "left": null,
       "margin": null,
       "max_height": null,
       "max_width": null,
       "min_height": null,
       "min_width": null,
       "object_fit": null,
       "object_position": null,
       "order": null,
       "overflow": null,
       "padding": null,
       "right": null,
       "top": null,
       "visibility": null,
       "width": null
      }
     },
     "fcb820f0030947e8aaae371dc73b01f6": {
      "model_module": "@jupyter-widgets/controls",
      "model_module_version": "2.0.0",
      "model_name": "HTMLStyleModel",
      "state": {
       "_model_module": "@jupyter-widgets/controls",
       "_model_module_version": "2.0.0",
       "_model_name": "HTMLStyleModel",
       "_view_count": null,
       "_view_module": "@jupyter-widgets/base",
       "_view_module_version": "2.0.0",
       "_view_name": "StyleView",
       "background": null,
       "description_width": "",
       "font_size": null,
       "text_color": null
      }
     }
    },
    "version_major": 2,
    "version_minor": 0
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
