Complete footage from a SAR drone shipped
A search-and-rescue drone streams video to a ground station over a link that drops packets. The pilot's view should give up late frames; the footage reviewed after the sortie should not. This guide sets up backfill: the drone journals its video, the ground station asks for every hole, and the archive completes during the flight or after it.
[qos] enabled = true on the drone and the ground station, the camera's stream classified as Video (RTP ports, an AF41 mark or a [[qos.flow]] rule), disk for the journal on the drone and for the capture on the ground, and Python 3 where you convert captures.On the drone
[qos]
enabled = true
[qos.classes.Video]
retain = true # journal every Video packet
[qos.retain]
path = "/media/footage" # removable storage; default is the state directory
max_bytes = "16 GiB" # the ring: oldest segment goes first
max_secs = 86400
[storage]
at_rest = "on" # journal sealed on disk
Run atlasd config check: it warns if the journal would be plaintext or if QoS is off. After a restart, atlasd retain status lists Video under retained classes and one line per stream with its sequence range.
On the ground station
[qos]
enabled = true
[qos.retain]
path = "/srv/footage" # captures land in <path>/atlas0.capture/
max_bytes = "64 GiB" # a full capture stops growing; it never deletes
[storage]
at_rest = "on"
Nothing names the drone: any stream that arrives marked as journaled is captured and its holes are requested. The defaults wait 2 s before asking, so reordering and FEC repair first, and ask at most every 2 s. Set backfill_max_kbps on the drone if the backfill must leave fixed headroom on a shared link; without it, backfill takes only capacity no live class is using.
Checking the archive
$ atlasd capture status
captures: 226.3 MiB of 65536.0 MiB under /srv/footage/atlas0.capture
requests sent 41 · answers 41 · backfill received 12972 · duplicates 0
10.0.0.2 Video stream 3d4c 100.00 % 187500 of 187500 missing 0 unrecoverable 0
Completeness is received packets over the stream's span, and the span includes the tail the live view never saw, because each answer carries the stream's highest sequence. missing is still requestable; unrecoverable is what the drone's journal no longer holds, because its ring turned over or a power cut took the last writes. On the dashboard the QoS tab shows the same figure in the Archive completeness card. After five minutes of a lossy link the archive completes about 14 s after the loss stops; a link cut mid-sortie completes once the path returns, and if the drone lands first, it completes when the drone is back on any link.
Turning the capture into a file
$ atlasd capture export 10.0.0.2 Video --out sortie.atlcap
$ atlas_capture.py info sortie.atlcap
$ atlas_capture.py sdp sortie.atlcap -o sortie.sdp --port 5004
$ ffmpeg -protocol_whitelist file,rtp,udp -i sortie.sdp -c copy sortie.mkv &
$ atlas_capture.py replay sortie.atlcap --to 127.0.0.1:5004
tools/atlas-capture/atlas_capture.py runs beside the daemon, never in it, with the standard library only. sdp takes --codec to match the stream's payload; replay re-sends it in sequence order at the original pace, and -c copy keeps the encode untouched. pcapng writes the inner packets with their original timestamps for a packet tool instead. An export is plaintext: keep it on media you protect. When the review copy is safe, atlasd retain clear on the drone and atlasd capture clear on the ground free the space.
Sizing the storage
The journal holds the stream at its own bitrate plus a little framing. At 6 Mbit/s that is about 2.7 GB an hour, so the 2 GiB default holds about 45 minutes; a 16 GiB card holds about six hours. Size the ground station's max_bytes for every drone it captures from.
When the archive should be a better encode
Backfill completes the stream that was sent live, at the live bitrate. When the review copy should be a higher-quality encode than the live stream, record whole chunks on the drone instead, with the encoder writing files, and copy them over the tunnel with any TCP transfer, which lands in the Bulk lane by default. It costs the uplink twice and needs its own storage, and the chunks arrive whole or not at all.
Boundaries
Frames are packets to Atlas: a frame lost on the drone before it reached the tunnel is not in the journal. A stream from an interconnect-mapped address is journaled but not backfilled. POST /api/capture/export answers up to 256 MiB; export larger captures with the CLI on the node.