Skip to content

Show a real flight on /low-latency, drone and pilot's screen side by side - #401

Merged
openipc-ai merged 7 commits into
masterfrom
low-latency-flight-ab
Oct 7, 2026
Merged

openipc-ai merged 7 commits into
masterfrom
low-latency-flight-ab

Conversation

@openipc-ai

Copy link
Copy Markdown
Collaborator

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-ab does the following:

    • It aligns the recordings. Both stamp frames with real time, so one offset relates them. Every ground-station frame is matched to its onboard frame by a 64×30 centre thumbnail; the offset is 1.0043 s, with a 2nd–98th percentile spread of 27 ms and a median match of 0.999. The run refuses if the offset drifts.
    • It cuts both originals onto one timeline without re-encoding, checked packet by packet.
    • It encodes lower rungs with their keyframes exactly where each original has them, and checks that too. The ground station gets an HEVC ladder plus an H.264 set, because Shaka keeps one codec family per presentation and Firefox on Linux has no HEVC.
    • It packages two static DASH presentations whose renditions start every segment at the same instant.
    • It writes the stats the page quotes.
  • 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 in check-config.sh --seam and reserved in reserved-paths.

  • FlightCompare is 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:

    • 97.0% of frames reached the pilot's screen;
    • 8 holds longer than 50 ms;
    • the longest hold was 315 ms.

    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 loss reads 0.0.

Checked

  • In real Google Chrome against nginx serving the real tree:
    • the two sides stay 3–4 ms apart over 30 s;
    • after seek and pause, both sit on the identical timestamp;
    • nothing is fetched before play;
    • no horizontal scroll at 390 px.
  • Playing it found and fixed six bugs:
    • Shaka's playRangeStart becomes the MSE append window, so Chrome dropped the drone side's first 4 s;
    • an aborted play() was read as a load failure;
    • a stale pause event froze the follower;
    • the follower settled at the edge of a whole-frame, then a half-frame, tolerance;
    • the packager writes a dynamic MPD unless told otherwise;
    • the split handle sat on the play button.
  • npm test (684), typecheck, service/run.sh test ./deploytest/..., deploy/nginx/check-config.sh --seam, and deploy/static/build.sh + check-bundle.sh all pass.

Already on the host

  • The media tree (2.6 GB) is uploaded to /srv/www/shared/media/flights/mabur-2026-10/v1/.
  • The nginx change is installed with push-nginx.sh --apply. It is additive; the dry-run diff was only the two /media/ blocks.
  • The source recordings are kept at /srv/www/flight-sources/mabur-2026-10/ with SHA256SUMS. The backup's IAM user refused a media-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.

…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.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Compare onboard and pilot-screen footage on /low-latency

✨ Enhancement ⚙️ Configuration changes 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Add a frame-aligned flight comparison with split, flicker, frame stepping, and rendition badges.
• Build adaptive DASH streams and page statistics from the same two recordings.
• Serve versioned media through nginx and document publishing and recovery.
Diagram

graph TD
  Sources["Flight recordings"] --> Pipeline["Alignment pipeline"] --> Media[("Versioned media")] --> Nginx["nginx media route"] --> Shaka["Shaka players"]
  Pipeline -->|statistics| Page["Low-latency page"] -->|mounts| Compare["Flight comparison"] -->|controls| Shaka
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Embed the existing R&D Player
  • ➕ Reuses its established comparison and synchronization behavior.
  • ➖ Gives the site less control over localized presentation, poster-first loading, and flight-specific statistics.
2. Publish one composited comparison video
  • ➕ Eliminates synchronization between browser players.
  • ➖ Loses the draggable comparison, independent adaptation, and access to each original recording.

Recommendation: Keep the page-native comparison and two aligned presentations: they support the intended interaction without fetching streams before play. Reusing synchronization code with the R&D Player would be worth considering if both projects can share it; neither an embed nor a composited video preserves the same page experience.

Files changed (21) +1364 / -1

Enhancement (7) +961 / -0
FlightCompare.tsxAdd an interactive, synchronized flight comparison +385/-0

Add an interactive, synchronized flight comparison

• Loads two DASH players after play and provides split or flicker viewing, transport controls, frame stepping, and quality badges. Keeps the follower aligned with the onboard video and pauses both sides when either lacks data.

frontend/apps/site/src/components/flight/FlightCompare.tsx

LowLatency.astroFeature the flight comparison below the hero +63/-0

Feature the flight comparison below the hero

• Mounts the poster-first comparison, displays statistics derived from the flight data, and adds localized context and credits.

frontend/apps/site/src/components/pages/LowLatency.astro

flight-mabur-2026-10.jsonVersion the published flight’s measurements +28/-0

Version the published flight’s measurements

• Records alignment, common playback window, frame counts, and hold measurements from the packaging run.

frontend/apps/site/src/data/flight-mabur-2026-10.json

flight.tsConnect flight statistics and media URLs to the page +29/-0

Connect flight statistics and media URLs to the page

• Exposes the versioned media path and page figures from the recorded statistics, plus a link that opens both presentations in the R&D Player.

frontend/apps/site/src/data/flight.ts

flight-sync.tsDefine frame-alignment and rendition rules +87/-0

Define frame-alignment and rendition rules

• Provides a pure seek-or-rate synchronization decision and helpers for identifying original, copied, and reduced renditions.

frontend/apps/site/src/lib/flight-sync.ts

align.pyAlign recordings and measure pilot-screen holds +150/-0

Align recordings and measure pilot-screen holds

• Matches frame thumbnails to estimate a constant offset, rejects weak or drifting matches, selects a common window, and calculates frame and hold statistics.

tools/flight-ab/align.py

run.shBuild and validate aligned DASH presentations +219/-0

Build and validate aligned DASH presentations

• Extracts alignment inputs, copies original streams onto one timeline, encodes codec-compatible ladders, and packages static DASH presentations. Validates timestamp and segment alignment and emits a poster and statistics.

tools/flight-ab/run.sh

Tests (2) +105 / -0
check-config.shProbe the media route in the nginx seam test +28/-0

Probe the media route in the nginx seam test

• Creates representative DASH files and checks successful serving, immutable caching, content types, range requests, CORS, and missing-file behavior.

deploy/nginx/check-config.sh

flight-sync.test.tsTest synchronization and rendition classification +77/-0

Test synchronization and rendition classification

• Covers drift thresholds, original-versus-copy selection, reduced-quality badges, and clock formatting.

frontend/apps/site/src/lib/flight-sync.test.ts

Documentation (8) +241 / -0
pages.en.ymlAdd English flight-comparison copy +25/-0

Add English flight-comparison copy

• Adds controls, recording context, telemetry explanation, credits, and carefully qualified pilot-screen statistics.

data/locales/pages.en.yml

pages.ru.ymlAdd Russian flight-comparison copy +25/-0

Add Russian flight-comparison copy

• Translates the comparison controls, recording context, telemetry, statistics, and credits.

data/locales/pages.ru.yml

pages.zh.ymlAdd Chinese flight-comparison copy +25/-0

Add Chinese flight-comparison copy

• Translates the comparison controls, recording context, telemetry, statistics, and credits.

data/locales/pages.zh.yml

RESTORE.mdDocument recovery of host-held flight media +6/-0

Document recovery of host-held flight media

• Explains that the published media and source recordings are not backed up and describes the rebuilt host’s dependency on obtaining the sources.

deploy/RESTORE.md

en.jsonAdd English frontend flight strings +25/-0

Add English frontend flight strings

• Adds the frontend translation keys used by the comparison and its surrounding page.

frontend/apps/site/src/i18n/en.json

ru.jsonAdd Russian frontend flight strings +25/-0

Add Russian frontend flight strings

• Adds Russian frontend translation keys for the comparison and its surrounding page.

frontend/apps/site/src/i18n/ru.json

zh.jsonAdd Chinese frontend flight strings +25/-0

Add Chinese frontend flight strings

• Adds Chinese frontend translation keys for the comparison and its surrounding page.

frontend/apps/site/src/i18n/zh.json

README.mdDocument the flight media workflow +85/-0

Document the flight media workflow

• Explains alignment, encoding, publishing, source locations and checksums, and limits on what the recording proves about link loss.

tools/flight-ab/README.md

Other (4) +57 / -1
org.openipcServe versioned flight media in production +26/-0

Serve versioned flight media in production

• Maps /media/ to host-held recordings with DASH MIME types, immutable caching, security headers, and CORS for the R&D Player origin.

deploy/nginx/sites-available/org.openipc

org.openipc.devServe versioned flight media in development +27/-0

Serve versioned flight media in development

• Adds the equivalent development media route, including its no-index directive.

deploy/nginx/sites-available/org.openipc.dev

reserved-pathsReserve /media/ for host-served recordings +2/-0

Reserve /media/ for host-served recordings

• Prevents the static site bundle from claiming the flight media route.

deploy/static/reserved-paths

package.jsonAdd Shaka Player to the site +2/-1

Add Shaka Player to the site

• Adds the DASH playback dependency used by the on-demand comparison island.

frontend/apps/site/package.json

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Restored sites lose the flight stream 🐞 Bug ☼ Reliability
Description
The restore plan excludes both the published media and its source recordings from off-host backups,
leaving the only documented copies on the host being restored. If that host is lost, the documented
restore cannot rebuild the streams used by /low-latency, so the page retains its poster but cannot
play the flight.
Code

deploy/RESTORE.md[R315-317]

+  two source recordings by `tools/flight-ab/run.sh` and uploaded as its README
+  says. The sources are on this host too (`/srv/www/flight-sources/`, not in
+  S3), so a rebuilt host needs them from wherever else they were kept. Until then the page shows its poster and the player says it cannot
Evidence
The new restore instructions explicitly exclude the media and sources from S3 and describe the
resulting playback failure; the publishing instructions locate the sources on that same host.

deploy/RESTORE.md[313-318]
tools/flight-ab/README.md[62-72]
frontend/apps/site/src/data/flight.ts[12-16]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The featured flight cannot be recovered from the documented backups after host loss because neither the published media nor its source recordings are stored off-host.
## Fix Focus Areas
- deploy/RESTORE.md[313-318]
- tools/flight-ab/README.md[62-72]
- deploy/backup-db.sh[11-29]
## Recommended Fix
Store verified copies of both source recordings in durable off-host storage, arrange the necessary backup permissions, and document and test how restore retrieves them and regenerates the media tree.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Failed encodes can publish stale footage ✓ Resolved
Description
run.sh launches rendition encodes in the background and uses a bare wait, which does not
propagate an individual job's failure, before checking only that output files are nonempty and have
matching keyframe times. On a rerun with a failed encode and a previous rendition in the persistent
work directory, those checks can accept old footage and package it beside the newly cut originals.
Code

tools/flight-ab/run.sh[R148-150]

+wait
+for f in onboard.1080p onboard.720p onboard.540p gs.720p-hevc gs.540p-hevc gs.h264 gs.720p gs.540p; do
+  [ -s "$work/$f.mp4" ] || die "encoding $f failed"
Evidence
The script reuses one work directory, backgrounds eight encodes, ignores their individual statuses
through no-argument wait, and subsequently validates file presence and keyframe positions rather
than freshness.

tools/flight-ab/run.sh[8-10]
tools/flight-ab/run.sh[135-153]
tools/flight-ab/run.sh[173-174]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A failed background extraction or encode does not fail the publishing run, and files retained from an earlier run can pass the later rendition checks.
## Fix Focus Areas
- tools/flight-ab/run.sh[69-80]
- tools/flight-ab/run.sh[135-154]
- tools/flight-ab/run.sh[160-174]
## Recommended Fix
Record each background PID and wait for each one individually, aborting if any fails. Remove or isolate outputs for a fresh run before starting jobs so validation cannot accept files left by an earlier attempt.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Buffering defeats pause and frame steps ✓ Resolved
Description
toggle() clears the buffering hold and calls play() because the held leader is paused, while
step() leaves the hold active and its resume intent intact. When either stream starves, the button
still reads Pause, but pressing it restarts playback, and stepping a frame is undone when the
buffers recover and the synchronization loop resumes both videos.
Code

frontend/apps/site/src/components/flight/FlightCompare.tsx[R230-238]

+    held.current = false;
+    if (a.paused) void a.play(); else a.pause();
+  };
+
+  const step = (by: number) => {
+    const a = lead.current;
+    if (!a || phase !== 'ready') return;
+    a.pause();
+    a.currentTime = Math.min(end, Math.max(start, a.currentTime + by));
Evidence
Starvation sets held and pauses the videos at lines 174–178, but line 164 continues to report
playing as true because held.current is true. At lines 230–231, toggle() clears the hold
before checking the now-paused leader and calls play() despite the Pause label; step() leaves
the hold set, allowing the recovery loop to resume both videos.

frontend/apps/site/src/components/flight/FlightCompare.tsx[160-184]
frontend/apps/site/src/components/flight/FlightCompare.tsx[226-239]
frontend/apps/site/src/components/flight/FlightCompare.tsx[341-346]
frontend/apps/site/src/components/flight/FlightCompare.tsx[164-178]
frontend/apps/site/src/components/flight/FlightCompare.tsx[226-232]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
During a buffering hold, the controls do not preserve the viewer's decision to pause or step to a frame: the displayed Pause control can start playback, and recovery can undo a frame step.
## Fix Focus Areas
- frontend/apps/site/src/components/flight/FlightCompare.tsx[160-185]
- frontend/apps/site/src/components/flight/FlightCompare.tsx[226-239]
## Recommended Fix
Track the viewer's desired playback state separately from the temporary buffering hold. In `toggle()`, determine whether the viewer sees playback as active before clearing the hold; if so, pause both videos and clear the intent to resume rather than calling `play()` on the held leader. Have frame stepping clear that intent too, and let the recovery loop call `play()` only while the intent remains active. Handle rejection from any new `play()` call so an `AbortError` is not left unhandled.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. A failed load leaves play unresponsive ✓ Resolved
Description
load() changes the phase to error on failure, but toggle() starts a load only from idle and
returns for every non-ready phase. The error overlay remains an enabled button that calls
toggle(), so a transient failure cannot be retried without reloading the page.
Code

frontend/apps/site/src/components/flight/FlightCompare.tsx[R227-231]

+    const a = lead.current;
+    if (phase === 'idle') { void load(); return; }
+    if (!a || phase !== 'ready') return;
+    held.current = false;
+    if (a.paused) void a.play(); else a.pause();
Evidence
The load catch sets error, both visible controls invoke toggle, and its phase guard neither
calls load nor plays when the phase is error.

frontend/apps/site/src/components/flight/FlightCompare.tsx[123-125]
frontend/apps/site/src/components/flight/FlightCompare.tsx[226-232]
frontend/apps/site/src/components/flight/FlightCompare.tsx[298-310]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
After an initial load failure, the visible play button remains enabled but cannot start another attempt.
## Fix Focus Areas
- frontend/apps/site/src/components/flight/FlightCompare.tsx[97-130]
- frontend/apps/site/src/components/flight/FlightCompare.tsx[226-232]
- frontend/apps/site/src/components/flight/FlightCompare.tsx[298-311]
## Recommended Fix
Give the error state an explicit retry action that cleans up the failed attempt, resets its playback state, and starts a fresh load when the viewer presses the overlay or main control.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Failed loads leave players attached ✓ Resolved
Description
load() starts both players under Promise.all, but its catch changes phase without destroying a
player that has already attached or loaded. If one side fails after the other succeeds, the
successful player and its buffers remain attached while the error overlay is shown, until the
component unmounts.
Code

frontend/apps/site/src/components/flight/FlightCompare.tsx[R123-125]

+    } catch {
+      setPhase('error');
+      return;
Evidence
Each side independently attaches and stores a player before p.load; a rejection from either side
reaches a catch with no cleanup, and destruction appears only in the unmount effect.

frontend/apps/site/src/components/flight/FlightCompare.tsx[103-125]
frontend/apps/site/src/components/flight/FlightCompare.tsx[208-210]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A failure on either side leaves players created during the same load attempt attached until the component unmounts.
## Fix Focus Areas
- frontend/apps/site/src/components/flight/FlightCompare.tsx[103-125]
- frontend/apps/site/src/components/flight/FlightCompare.tsx[208-210]
## Recommended Fix
Track both players from creation, settle or cancel outstanding load work on failure, destroy every player from that attempt, and clear their references before showing the error or permitting a retry.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View review recommended (3)
6. Playback outages stall without an error ✓ Resolved
Description
load() is the only path that sets the error phase, and the ready-state loop has no player or media
error handler. If a stream fails after initial loading and its buffer runs dry, the loop holds both
videos until readiness returns while the controls continue to present normal playback rather than a
failure or recovery action.
Code

frontend/apps/site/src/components/flight/FlightCompare.tsx[R173-180]

+      const starved = a.readyState < 3 || b.readyState < 3;
+      if (!a.paused && starved && !a.seeking && !b.seeking) {
+        held.current = true;
+        a.pause();
+        b.pause();
+        return;
+      }
+      if (held.current && !starved) {
Evidence
The registered player events cover adaptation and variant changes but not errors; after the load
catch, starvation only pauses and conditionally resumes the videos, with no transition to an error
state.

frontend/apps/site/src/components/flight/FlightCompare.tsx[117-127]
frontend/apps/site/src/components/flight/FlightCompare.tsx[171-190]
frontend/apps/site/src/components/flight/FlightCompare.tsx[298-310]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Permanent stream failures after initial load leave the comparison held with no error state or recovery path.
## Fix Focus Areas
- frontend/apps/site/src/components/flight/FlightCompare.tsx[117-125]
- frontend/apps/site/src/components/flight/FlightCompare.tsx[171-190]
- frontend/apps/site/src/components/flight/FlightCompare.tsx[298-311]
## Recommended Fix
Handle player and media errors after loading, distinguish recoverable buffering from a failed stream, and expose an error state with a way to reload both synchronized sides.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. Server outages are blamed on browsers ✓ Resolved
Description
load() discards every import, attachment, and manifest-load exception in one catch and renders the
same message used for an unsupported browser. When the media tree is absent after a restore or a
manifest request fails, a compatible visitor is told that their browser cannot play the stream, and
the underlying failure is not logged.
Code

frontend/apps/site/src/components/flight/FlightCompare.tsx[R123-125]

+    } catch {
+      setPhase('error');
+      return;
Evidence
The catch covers both the explicit browser-support check and both manifest loads, the English error
text blames the browser, and the restore instructions identify absent media as a condition that
makes the player fail.

frontend/apps/site/src/components/flight/FlightCompare.tsx[97-125]
data/locales/pages.en.yml[460-462]
deploy/RESTORE.md[313-318]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The player labels all initial load failures as browser incompatibility and drops the error needed to diagnose a media or network outage.
## Fix Focus Areas
- frontend/apps/site/src/components/flight/FlightCompare.tsx[97-125]
- frontend/apps/site/src/components/flight/FlightCompare.tsx[298-310]
- data/locales/pages.en.yml[460-471]
## Recommended Fix
Separate the browser-support check from import and stream-loading failures, retain or log the actual exception for diagnosis, and display an appropriate localized message for media or network failures.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. Short recordings crash alignment ✓ Resolved
Description
coarse_offset() skips candidates with fewer than 600 samples on its 0.1-second grid and then
returns best[1] without checking whether a candidate existed. For an otherwise valid pair of short
recordings, such as a 30-second flight, every candidate is skipped and run.sh stops with a
traceback before it can cut or package either side.
Code

tools/flight-ab/align.py[R61-66]

+        if n < 600:
+            continue
+        c = float((sa[i0:i0 + n] * sb[j0:j0 + n]).mean())
+        if best is None or c > best[0]:
+            best = (c, lag / 10)
+    return best[1]
Evidence
The matcher samples at 0.1-second intervals, rejects every overlap below 600 samples, and
dereferences best even when none qualified; run.sh invokes it before producing the media.

tools/flight-ab/align.py[51-66]
tools/flight-ab/run.sh[77-92]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The coarse matcher cannot process recordings shorter than its fixed 600-sample minimum and dereferences an unset result.
## Fix Focus Areas
- tools/flight-ab/align.py[51-76]
- tools/flight-ab/run.sh[69-80]
## Recommended Fix
Choose a candidate-length threshold appropriate to the available overlap, test alignment with short recordings, and return a clear validation error if there is genuinely too little material to align.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can route each severity your way: inline, summary, both, or drop

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread deploy/RESTORE.md
Comment thread tools/flight-ab/run.sh Outdated
Comment thread frontend/apps/site/src/components/flight/FlightCompare.tsx Outdated
Comment thread frontend/apps/site/src/components/flight/FlightCompare.tsx
Comment thread frontend/apps/site/src/components/flight/FlightCompare.tsx Outdated
Comment thread frontend/apps/site/src/components/flight/FlightCompare.tsx Outdated
Comment thread frontend/apps/site/src/components/flight/FlightCompare.tsx Outdated
Comment thread tools/flight-ab/align.py Outdated
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.
@openipc-ai
openipc-ai merged commit c23ed99 into master Oct 7, 2026
2 checks passed
@openipc-ai
openipc-ai deleted the low-latency-flight-ab branch October 7, 2026 04:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant