Connecting sources
A source is where a project’s raw data lives. Register it once; every run reads from it. Registering a source does not ingest anything and does not spend.
What Euler reads
| Format | Becomes |
|---|---|
mcap, ros1_bag, ros2_bag | episodes with decoded telemetry and a timing summary per topic |
mp4+parquet | episodes with per-frame state and action |
hdf5 | episodes from ALOHA-style and multimodal HDF5 recordings |
lerobot_v2, lerobot_v3 | episodes from an existing LeRobot dataset |
assets | one asset per loose video or image (a sibling caption file becomes its task text) |
directory | auto-detected: Euler looks at the files and picks one of the above |
You rarely need to name the format: a directory or asset source is inspected at run time and routed to the right reader.
Uploading files
In Sources, drag in files or a folder. Large files go up in resumable chunks: each chunk is its own short request, an interrupted upload resumes where it stopped, and the server checks the whole-file hash before it registers the source. From code, the Python and TypeScript SDKs do the same with one call:
from euler_sdk import EulerClient
client = EulerClient("https://api.euler.sudotank.com", api_key="<your API token>")
client.upload_file("kitchen-pilot", "/data/session-01.mp4", source_id="session-01")
Behind it are POST /v1/projects/{id}/uploads and its part, status and complete
routes. For a small zip there is also the one-request
POST /v1/projects/{id}/sources/upload; anything large should use the chunked
route.
The parts of an upload that never completed keep taking space until they are
discarded: Sources lists unfinished uploads under the drop zone with a
Discard button and shows how much space the project uses, and from code
GET /v1/projects/{id}/uploads lists them and
DELETE /v1/projects/{id}/uploads/{upload_id} removes one. Completing a large
upload briefly needs the file’s size free a second time on the storage volume,
so discarding abandoned uploads is the first thing to try when completion is
refused for lack of space.
To use an uploaded source in another project as well, copy it rather than
uploading it again: the source card’s Copy button asks for the project
(and, optionally, which files), and only the original files are copied, linked
to the same stored bytes where the storage allows. The new project runs its own
layers on the copy; annotations stay with the original. From code it is
POST /v1/projects/{id}/sources/{source_id}/copy with a target_project_id.
Reusing a source in another project
has the details.
Your own bucket
Register a bucket prefix and Euler reads it in place; you do not copy data in first.
curl -fsS -X POST -H "Authorization: Bearer $EULER_TOKEN" -H "Content-Type: application/json" \
"$EULER_BASE_URL/v1/projects/$PROJECT/sources" \
-d '{"id": "shift-a", "name": "Shift A", "format": "directory",
"uri": "s3://acme-robot-logs/2026-09/shift-a/"}'
curl -fsS -X POST -H "Authorization: Bearer $EULER_TOKEN" \
"$EULER_BASE_URL/v1/projects/$PROJECT/sources/shift-a/test-connection"
gs://ands3://work, plus S3-compatible stores through an endpoint URL.- Credentials: seal a service-account or access-key JSON with
POST /v1/secrets/sealand pass it ascredentials.sealed_secret; it is encrypted at rest, used in memory only and never logged. A publicly readablegs://bucket needs no credentials. - Test connection lists a few objects with the resolved credentials and says whether the bucket is reachable.
- The pull is bounded in file count and bytes, and object keys that try to escape the destination are refused.
How long recordings become episodes
An action camera worn for a whole shift produces one long file holding many separate stretches of work. With the session split on, Euler cuts each recording into episodes at idle stretches and scene changes, and each episode gets its own clean clip. It is off by default: each recording is one episode.
| In Sources | Field | Default | Meaning |
|---|---|---|---|
| Split long recordings into episodes | enabled | off | turn the split on |
| Shortest episode | min_episode_s | 4 s | a shorter piece is merged into its neighbour |
| Longest episode | max_episode_s | 120 s | a longer piece is divided at its quietest points |
| Idle stretch that ends one | min_idle_s | 3 s | how long nothing has to happen to end an episode |
| Motion below which it is idle | idle_floor | 0.01 | motion level (0 to 1) at or below which a frame counts as idle |
| Also cut at scene changes | use_scene_changes | on | a hard cut in the content ends an episode |
Idle material between episodes is dropped. The setting applies to the next run of a source; episodes already made are not re-split.
curl -fsS -X PUT -H "Authorization: Bearer $EULER_TOKEN" -H "Content-Type: application/json" \
"$EULER_BASE_URL/v1/projects/$PROJECT/ingest/settings" \
-d '{"episode_split": {"enabled": true, "min_episode_s": 4, "max_episode_s": 90,
"min_idle_s": 3, "idle_floor": 0.01, "use_scene_changes": true}}'
A shortest episode longer than the longest is refused with 422.
What Euler keeps from a video
For each video, Euler writes review and processing copies of the clip, a frame map, a motion track and the keyframes. From an action camera that records its own telemetry it also keeps the accelerometer, gyroscope, gravity, orientation and exposure streams on the video’s clock; those drive the sensor graphs and several readiness checks. Location and face streams are kept out of the review screen and out of every export.
Moving a source to another project
A source and its clips belong to one project. To reorganise without re-ingesting, move it: in Sources, the source card’s Move button sends the source, its clips and their finished annotations to another project. Nothing is re-run and nothing is spent.
curl -fsS -X POST -H "Authorization: Bearer $EULER_TOKEN" -H "Content-Type: application/json" \
"$EULER_BASE_URL/v1/projects/$PROJECT/sources/session-01/transfer" \
-d '{"target_project_id": "kitchen-pilot-v2"}'
The move is refused, with the reason, unless the target is a different, empty project in the same workspace and no run is active in either project. It works for data uploaded into Euler; a bucket source cannot be moved yet.
Deleting a project deletes the clips uploaded into it, even if another project reads them. The confirmation says so. Move the sources you want to keep first.
Next
- Decide what the run produces: Pipeline settings.
- Start it: Running the pipeline.
- Container details for MCAP and HDF5: Ingest recipe.