> This is the Markdown version of the page. For the complete Lattice Developers documentation index, fetch https://developer.anduril.com/llms.txt. Append .md to any page URL for its clean Markdown. ## Stream live video into Lattice The **Lattice Video API** is now available in `Preview`. Register a video source, attach it to an asset entity, and the feed shows up on the common operational picture (COP) alongside every other entity in the scene—a drone camera, a fixed tower sensor, an encoder behind a NAT gateway, all through one consistent API. The API covers the full stream lifecycle—register, attach, list, inspect, and stop across the Lattice SDKs in **Python, Go, Java, and TypeScript (REST)** and in **gRPC**. ![Shows an example live camera feed playing for a selected asset in Lattice.](/_fern-files/developer.anduril.com/anduril.docs.buildwithfern.com/2edb4fcc76cbbf5d6fd0e34191732654fc189aea27ff16cbecf388b1da322c55/assets/images/screenshots/lattice-ui-live-feed.gif) ### Supported protocols Lattice ingests video over three transports: * **RTSP**: provide a Real Time Streaming Protocol (`rtsp://`) URL and Lattice pulls the frames. Use it when your source can serve an RTSP endpoint, like an IP camera or a [MediaMTX](https://github.com/bluenviron/mediamtx) relay. * **SRT**: Lattice allocates a listener and returns the endpoint your producer pushes to, with an optional passphrase for AES encryption. Use it for low-latency, push-based delivery from encoders and devices behind a NAT gateway. * **MPEG-TS**: Lattice supports MPEG-TS at the edge, for closed networks. Over the public internet you can't start an MPEG-TS stream, but you can still list or inspect its `IngressStream` object. ### Start an ingress stream After publishing a camera asset entity, create an ingress stream and attach it to the entity so the feed appears in the UI. The example below starts an RTSP stream—the API looks the same across every Lattice SDK: **`Python (REST)`** ```python title="Python (REST)" from anduril import Lattice, RtspSettings client = Lattice( base_url=f"https://{lattice_endpoint}", token=environment_token, ) stream = client.video.create_ingress_stream( title="pi-cam-01", rtsp=RtspSettings(url="rtsp://:/cam"), ) print(stream.ingress_id) ``` **`Go (REST)`** ```go title="Go (REST)" package main import ( "context" "fmt" "os" Lattice "github.com/anduril/lattice-sdk-go/v5" "github.com/anduril/lattice-sdk-go/v5/client" "github.com/anduril/lattice-sdk-go/v5/option" ) func main() { latticeEndpoint := os.Getenv("LATTICE_ENDPOINT") environmentToken := os.Getenv("ENVIRONMENT_TOKEN") c := client.NewClient( option.WithToken(environmentToken), option.WithBaseURL(fmt.Sprintf("https://%s", latticeEndpoint)), ) stream, _ := c.Video.CreateIngressStream(context.TODO(), &Lattice.CreateIngressStreamRequest{ Title: "pi-cam-01", Rtsp: &Lattice.RtspSettings{URL: Lattice.String("rtsp://:/cam")}, }) fmt.Println(stream.GetIngressID()) } ``` **`Java (REST)`** ```java title="Java (REST)" import com.anduril.Lattice; import com.anduril.resources.video.requests.CreateIngressStreamRequest; import com.anduril.types.CreateIngressStreamResponse; import com.anduril.types.RtspSettings; Lattice client = Lattice.builder() .url(String.format("https://%s", latticeEndpoint)) .token(environmentToken) .build(); CreateIngressStreamResponse stream = client.video().createIngressStream( CreateIngressStreamRequest.builder() .title("pi-cam-01") .rtsp(RtspSettings.builder().url("rtsp://:/cam").build()) .build()); System.out.println(stream.getIngressId()); ``` **`TypeScript (REST)`** ```js title="TypeScript (REST)" import { LatticeClient } from "@anduril-industries/lattice-sdk"; const client = new LatticeClient({ baseUrl: `https://${latticeEndpoint}/api/v1`, token: environmentToken, }); const stream = await client.video.createIngressStream({ title: "pi-cam-01", rtsp: { url: "rtsp://:/cam" }, }); console.log(stream.ingressId); ``` **`Rust (gRPC)`** ```rust title="Rust (gRPC)" use anduril_lattice_sdk_community_neoeinstein_prost::anduril::videomanager::v1::{ create_ingress_stream_request::Ingress, CreateIngressStreamRequest, RtspSettings, }; let stream = client .create_ingress_stream(CreateIngressStreamRequest { title: "pi-cam-01".to_string(), ingress: Some(Ingress::Rtsp(RtspSettings { url: Some("rtsp://:/cam".to_string()), })), ..Default::default() }) .await? .into_inner(); println!("{}", stream.ingress_id); ``` Attach the returned `ingress_id` to your asset entity through the entity's `media` component, and the live feed becomes selectable on the COP. ### Manage and re-publish streams Once streams are live, the Video API lets you operate them: * **List and inspect**: enumerate active ingress streams and retrieve a single stream's status, configuration, and associated egress identifiers. * **Stop**: stopping a stream archives it. The record remains retrievable, but the stream transitions to `STREAM_STATUS_ARCHIVED` and no longer appears in listings. * **Egress**: re-publish an active ingress stream to downstream consumers over RTSP or SRT. HTTP Live Streaming (HLS) egress is planned. ### Get started See the following pages in the *Lattice SDK guide*: * [Video overview](/guides/video/overview) reviews the API surface, the `IngressStream` object, and the stream lifecycle. * [Create streams](/guides/video/create-streams) walks through publishing a camera asset and starting an RTSP or SRT ingress stream. * [Manage streams](/guides/video/manage-streams) covers listing, retrieving, stopping, and re-publishing streams. If you are new to the Lattice SDK, [install the SDK](/guides/getting-started/set-up#get-the-sdk) in your language of choice, then follow the video guides above.