Video upload#

Upload a video and give it a start time, so it plays back in step with your time-series data.

In code#

from datetime import datetime, timezone
from nominal.core import NominalClient

client = NominalClient.from_profile("default")
dataset = client.get_dataset("<ri.catalog.instance.dataset.identifier>")

file = dataset.add_video("video.mp4", channel="camera", start=datetime(2026, 1, 1, 14, 0, tzinfo=timezone.utc))
file.poll_until_ingestion_completed()  # raises NominalIngestError if the ingest fails

LabVIEW example that uploads a video starting at the current time, with labels and properties

use nominal::core::{VideoCreate, VideoIngest};

let client = nominal::NominalClient::from_profile("default")?;
let start: chrono::DateTime<chrono::Utc> = "2026-01-01T14:00:00Z".parse()?;
client.ingest()
    .upload_video("video.mp4", VideoCreate::new("Camera"), VideoIngest::starting_at(start))
    .await?;
import (
	"bytes"
	"os"

	ingestapi "github.com/nominal-io/nominal-api-go/ingest/api"
	nominalapi "github.com/nominal-io/nominal-api-go/io/nominal/api"
	videoapi "github.com/nominal-io/nominal-api-go/scout/video/api"
	uploadapi "github.com/nominal-io/nominal-api-go/upload/api"
	"github.com/palantir/conjure-go-runtime/v2/conjure-go-client/httpclient"
	"github.com/palantir/pkg/rid"
	"github.com/palantir/pkg/safelong"
)

// httpClient is a conjure-go-runtime httpclient.Client for your Nominal REST API URL,
// and token is your API key as a bearertoken.Token
data, _ := os.ReadFile("video.mp4")
size := safelong.SafeLong(len(data))
path, _ := uploadapi.NewUploadServiceClient(httpClient).UploadFile(ctx, token, "video.mp4", &size, nil,
	httpclient.RequestBodyInMemory(bytes.NewReader(data)))
datasetRid, _ := rid.ParseRID("<ri.catalog.instance.dataset.identifier>")
ingestapi.NewIngestServiceClient(httpClient).Ingest(ctx, token, ingestapi.IngestRequest{
	Options: ingestapi.NewIngestOptionsFromVideoV2(ingestapi.VideoOptsV2{
		Source:  ingestapi.NewIngestSourceFromS3(ingestapi.S3IngestSource{Path: string(path)}),
		Target:  ingestapi.NewDatasetIngestTargetFromExisting(ingestapi.ExistingDatasetIngestDestination{DatasetRid: datasetRid}),
		Channel: "camera",
		TimestampManifest: videoapi.NewVideoFileTimestampManifestFromNoManifest(videoapi.NoTimestampManifest{
			StartingTimestamp: nominalapi.Timestamp{Seconds: 1767276000}, // 2026-01-01T14:00:00Z
		}),
	}),
})

In the Nominal app#

  1. Open the dataset’s page and click UPLOAD DATA. To find the dataset, in the sidebar click Data, then Data sources.

  2. Drop the video onto Upload files, or click SELECT FILES and pick it.

  3. In the video’s settings, choose or type a Channel, such as camera, and check the Start time. Nominal fills in the start time when the file records one.

  4. Click CONFIRM & INGEST.