Repository navigation
Show a real flight on /low-latency, drone and pilot's screen side by side - #401
Conversation
…side gilankpam recorded one six-minute mabur flight twice: on the drone (H.264 1080p60, 19 Mbit/s) and on the ground station (the pilot's screen with the link's OSD, HEVC). The page now opens with both, frame-aligned, in a split slider or a flicker, so the claim the page makes is shown rather than stated. - tools/flight-ab aligns the two recordings (one constant offset, 1.004 s, found per frame and refused if it drifts), cuts both originals without re-encoding onto one timeline, encodes keyframe-aligned lower rungs (an HEVC ladder and an H.264 set for the ground station), packages two static DASH presentations, and writes the stats the page quotes. - nginx serves them from /srv/www/shared/media/ at /media/ (prod and dev), versioned and immutable for a year, with the DASH types and CORS for the R&D Player only; the seam check probes all of it, and /media/ is reserved. - FlightCompare is a Preact island: a poster until play, then two Shaka players (loaded on demand) kept on the same frame the R&D Player's way, each side saying which rendition it shows. - The numbers are the run's own: 97.0% of frames reached the pilot's screen, eight holds over 50 ms, the longest 315 ms.
PR Summary by QodoCompare onboard and pilot-screen footage on /low-latency
AI Description
Diagram
High-Level Assessment
Files changed (21)
|
Code Review by Qodo
1. Restored sites lose the flight stream
|
shaka-packager writes presentationTimeOffset = the first segment's timestamp. For the ground station that is 0.7046 s, where its first frame sits on the drone's timeline, and a DASH player takes it to mean "this media time is the start of the period": it played that frame at 0 and showed the whole side 0.70 s early. Measured in Chrome by matching the two displayed pictures: best match +42 frames everywhere before, 0 frames (0.999) after. The pipeline now strips the attribute and refuses a manifest that carries one. The corrected manifests are published as v2 -- /media/ is immutable for a year, so v1's would have outlived any fix in place; the segments are byte-identical and hard-linked on the host.
… stalling The page sells the stack first again: the flight moved from the top to a band under "How fast, really", the evidence beside the claim, with a heading, two sentences and the credit. The stat cards are gone. Stress-testing the player (25+ runs in Chrome) found it stalling about one start in six and after some seeks, the ground station's side left seeking with nothing buffered: - the leader's seek handler moved the follower before Shaka's first append; it now waits until the follower has a picture, and the hold lines it up; - seeking and Shaka's own buffering count as starved, so the leader waits instead of running on while the follower seeks (a chase that never ended); - a starved follower is left playing during a hold -- Shaka restarts a stalled stream only while it plays -- and is paused only when it has data; - resuming re-seeks the follower only for a real gap (> 200 ms), not the few milliseconds it moved while waiting; re-seeking those had the two take turns being ready for good; - the playhead starts 5 ms inside the ground station's first frame, not on it, and Pause during a hold stops both; - the island hydrates when idle rather than when visible, so a click on a slow link is not lost before it hydrates. After: 20 of 20 full runs clean (start, 30 s within 4 ms, seek, resume in ~0.4 s), 40 of 40 starts, pictures matched at 0 frames (0.999).
The split slider is the comparison; the Split/Flicker switch under it is gone. The drone sits still on the ground for the first seven seconds, so the page's window now starts eight seconds in -- trimmed in the player, not the streams -- and the clock counts from there (0:00 / 5:52). The R&D Player link opens at the same moment.
From Qodo's review of #401: - A failed load, or a stream that fails critically mid-flight, now tears both players down, logs the error and offers "The flight did not load. Try again", which retries; only a browser without MSE is told it cannot play. - A frame step during a buffering hold releases the hold, so the step is not undone when the buffers recover. - run.sh waits for each background job by pid and stops on a failure, and removes the previous run's renditions before encoding, so a failed encode cannot ship a stale one. - align.py scales its minimum overlap to the recordings, so a short flight aligns (a 35 s slice: 1.0055 s against the full flight's 1.0043 s) instead of crashing.
gilankpam (mabur, built on devourer) gave us one real six-minute flight recorded twice, for publishing:
onboard.mp4, on the drone: H.264 1080p60, 19 Mbit/s;record-0015.mp4, on the ground station: the pilot's screen with mabur's OSD (lat, rssi, snr, mcs, loss), HEVC, re-encoded at 8 Mbit/s when it was saved./low-latency now opens with both, frame-aligned, as an A/B: a split slider or a flicker, frame stepping, and a badge per side naming the rendition it shows.
How
tools/flight-abdoes the following:nginx:
/media/serves/srv/www/shared/media/in prod and dev, versioned and immutable for a year, with the DASH types and CORS for the R&D Player's origin only. Probed incheck-config.sh --seamand reserved inreserved-paths.FlightCompareis a Preact island. It shows a poster until play and fetches nothing before then. On play it loads two Shaka players on demand (dash build, 174 kB gz) and keeps them on one frame the R&D Player's way: a seek beyond 200 ms, a ±3% rate nudge beyond a quarter frame. The thresholds are a pure function with tests.The page's numbers come from the same run as the streams:
The copy says "reached the pilot's screen", not "delivered by the link". The recording cannot tell air loss from a DVR drop, and the OSD's
lossreads 0.0.Checked
playRangeStartbecomes the MSE append window, so Chrome dropped the drone side's first 4 s;play()was read as a load failure;pauseevent froze the follower;npm test(684), typecheck,service/run.sh test ./deploytest/...,deploy/nginx/check-config.sh --seam, anddeploy/static/build.sh+check-bundle.shall pass.Already on the host
/srv/www/shared/media/flights/mabur-2026-10/v1/.push-nginx.sh --apply. It is additive; the dry-run diff was only the two/media/blocks./srv/www/flight-sources/mabur-2026-10/withSHA256SUMS. The backup's IAM user refused amedia-sources/prefix in S3, so they are not in the backup yet.Not yet tested: the HEVC path. The headless Chrome used had no HEVC, so it played the H.264 copy; dev validation in Safari or Chrome with hardware decode covers it.