Watch a flight, live or recorded
A gusty hover hop on real ArduPilot SITL, rendered from its own log by render_video: 6 m/s from the west with seeded Dryden gusts, climb to 9 m, hold 12 s, land in QLAND.
Every picture shows the same scene in one of three layouts:
fpv: a nose camera with a HUD. It shows height, airspeed, climb rate and the true wind with its gust, plus the mode, armed state, throttle, lift-motor demand, current, voltage, energy and the latest autopilot messages.chase: a camera behind and above the aircraft, showing its track, its shadow and the wind on a compass.pip: the FPV view with the chase view inset.
Watch a session live
Section titled “Watch a session live”video_feed(session_id="d224b4"){ "on": true, "layout": "pip", "viewers": 0, "encoder": "h264_nvenc", "vlc": "vlc http://127.0.0.1:8440/video.ts", "page": "http://127.0.0.1:8440/", "frame": "http://127.0.0.1:8440/frame.jpg" }Open the vlc line in VLC or mpv, or the page in a browser, which plays an MJPEG stream with nothing to install. The feed listens on MCARDUPILOT_VIDEO_PORT_BASE (8400) plus the instance number, on 127.0.0.1 unless MCARDUPILOT_VIDEO_HOST says otherwise. To change the view live, call video_feed(session_id, layout="chase"). on=false stops the feed, and closing the session stops it too.
The aircraft’s position and attitude come from SITL itself. Every session launches SITL with --enable-fgview, which makes it send its simulated state to UDP 5503 + 10 × instance at every physics step, as it would to FlightGear. That costs SITL about 4% more CPU and changes nothing about the flight. A SITL that sends nothing still gets a picture, from the session’s telemetry at a few hertz.
Record a flight
Section titled “Record a flight”Ask for the recording when you open the session:
open_sitl(label="gusty-hop", record_video="pip", wind={...})...close_sitl(session_id) # "video": {"video_id": "a09ddb", "status": "rendering", ...}video_status(video_id="a09ddb")Or render any log afterwards. A log is named the way log_summary takes it: a session id, a kept log’s name, or a path.
render_video(log="20261003T225739Z-video-demo-gusty-hop.BIN", layout="chase")render_video(log="...", t0_s=60, t1_s=75) # just the part you care aboutA recording is drawn from SITL’s own records in the log, so it shows the truth, not the estimator:
- Pose: from
SIM, about 10 Hz for attitude and position, andSIM2, a few hundred hertz for position and velocity. - Wind: from the
SIM_WIND_SPDandSIM_WIND_DIRchanges the gust model sent. - Speed: from the logged
SIM_SPEEDUP.
Log time is sim time, so the video plays at the speed the aircraft flew, whatever speedup the session ran at, and idle-paced pauses disappear. By default it runs from four seconds before arming to four seconds after disarming. Rendering runs faster than real time: the 51-second flight above took 33 s at 960×540, 5 MB with NVENC.
A kept log’s video goes beside it as <stem>.<layout>.mp4. The log budget counts it and deletes it with the log, and pin_log spares both. A log the server doesn’t own, such as a live session’s or another project’s, renders into <data_dir>/videos instead, so nothing is written next to files that belong to someone else.
A log from a real aircraft has no SIM records. It still renders, from the estimator’s attitude and position, and its wind is then labelled WIND est.
Let the agent look
Section titled “Let the agent look”video_frame(session_id="d224b4") # the picture nowvideo_frame(log="...gusty-hop.BIN", t_s=75.0, layout="chase")video_frame returns one frame as an image. For a session with a live feed it is exactly the frame on the viewer’s screen. It’s the quickest way for an agent to check what a person is looking at before describing it.
Requirements
Section titled “Requirements”ffmpeg on PATH. Encoding uses NVENC when ffmpeg can open it, else libx264. Set MCARDUPILOT_VIDEO_ENCODER to choose one. MCARDUPILOT_VIDEO_SIZE (960x540) and MCARDUPILOT_VIDEO_FPS (30) apply to both live feeds and renders.