feat(lab): seal full RAVNOVES004TREE semantic review

This commit is contained in:
DCCONSTRUCTIONS
2026-08-29 13:37:57 +03:00
parent 24b65926fe
commit 9dec37a8a9
12 changed files with 1494 additions and 30 deletions
@@ -187,12 +187,15 @@ Write-Output "PHASE=e4-preflight-complete"
$runToken = [Guid]::NewGuid().ToString("N")
$workRoot = Join-Path $tmpRoot ("{0}-e4-{1}" -f $job.job_id, $runToken)
$framesRoot = Join-Path $workRoot "frames"
$decodedFramesRoot = Join-Path $workRoot "decoded-by-pts"
$streamPath = Join-Path $workRoot "camera.mp4"
$ptsPath = Join-Path $workRoot "pts.json"
$packetsPath = Join-Path $workRoot "packets.csv"
$decodeRepairPath = Join-Path $workRoot "decode-repair.json"
$timelinePath = Join-Path $workRoot "timeline.jsonl"
$publishRoot = Join-Path $derivedRoot (".{0}-e4-{1}.publish" -f $job.job_id, $runToken)
$stagingRoot = Join-Path $publishRoot "output"
$null = New-Item -ItemType Directory -Path $framesRoot
$null = New-Item -ItemType Directory -Path $decodedFramesRoot
$null = New-Item -ItemType Directory -Path $publishRoot
$totalWatch = [Diagnostics.Stopwatch]::StartNew()
$completed = $false
@@ -230,29 +233,69 @@ try {
$extractWatch = [Diagnostics.Stopwatch]::StartNew()
Write-Output "PHASE=e4-frame-extraction-start"
& ffmpeg -hide_banner -loglevel fatal -i $streamPath -map 0:v:0 -fps_mode passthrough -frames:v $activeFrameCount (Join-Path $framesRoot "frame-%06d.png")
& ffprobe -v error -select_streams v:0 -show_packets -show_entries packet=pts,flags -of csv=p=0 -o $packetsPath $streamPath
Assert-LastExitCode "LAB E4 packet timestamp probe"
$packetRows = @(Get-Content -LiteralPath $packetsPath | Select-Object -First $activeFrameCount)
if ($packetRows.Count -ne $activeFrameCount) {
throw "LAB E4 packet count differs from the requested camera epoch"
}
& ffmpeg -hide_banner -loglevel error `
-hwaccel cuda -hwaccel_output_format cuda -c:v h264_cuvid `
-err_detect ignore_err -flags +output_corrupt -copyts `
-i $streamPath -map 0:v:0 -vf "hwdownload,format=nv12" `
-fps_mode passthrough -enc_time_base demux -frames:v $activeFrameCount `
-frame_pts 1 (Join-Path $decodedFramesRoot "frame-%d.png")
Assert-LastExitCode "LAB E4 camera extraction"
& ffprobe -v error -select_streams v:0 -show_entries frame=best_effort_timestamp_time -of json $streamPath | Set-Content -LiteralPath $ptsPath -Encoding utf8
Assert-LastExitCode "LAB E4 camera timestamp probe"
$decodedCount = @(Get-ChildItem -LiteralPath $decodedFramesRoot -File -Filter "frame-*.png").Count
$repairs = @()
$packetPts = @()
for ($index = 0; $index -lt $activeFrameCount; $index++) {
$columns = ([string]$packetRows[$index]).Split(",")
if ($columns.Count -lt 2) {
throw "LAB E4 packet timestamp row is malformed"
}
$pts = [int64]::Parse($columns[0].Trim(), [Globalization.CultureInfo]::InvariantCulture)
$packetPts += $pts
$decodedPath = Join-Path $decodedFramesRoot ("frame-{0}.png" -f $pts)
$canonicalPath = Join-Path $framesRoot ("frame-{0:D6}.png" -f ($index + 1))
if (Test-Path -LiteralPath $decodedPath -PathType Leaf) {
Move-Item -LiteralPath $decodedPath -Destination $canonicalPath
continue
}
if ($index -eq 0 -or $repairs.Count -ge 1) {
throw "LAB E4 source contains more than one recoverable decoder gap"
}
$previousPath = Join-Path $framesRoot ("frame-{0:D6}.png" -f $index)
Copy-Item -LiteralPath $previousPath -Destination $canonicalPath
$repairs += [ordered]@{
sequence = $index + 1
packet_pts = $pts
method = "duplicate-previous-decoded-frame"
}
}
$decodedFrames = @(Get-ChildItem -LiteralPath $framesRoot -File -Filter "frame-*.png")
$ptsDocument = Get-Content -LiteralPath $ptsPath -Raw | ConvertFrom-Json
$pts = @($ptsDocument.frames)
if ($decodedFrames.Count -ne $activeFrameCount -or $pts.Count -lt $activeFrameCount) {
if ($decodedFrames.Count -ne $activeFrameCount) {
throw "Decoded LAB E4 frame count differs from the requested camera epoch"
}
$firstEpochSeconds = [double]::Parse(
([string]$pts[0].best_effort_timestamp_time).Trim(),
[Globalization.CultureInfo]::InvariantCulture
)
$decodeRepair = [ordered]@{
schema_version = "missioncore.recorded-video-decode-repair/v1"
decoder = "ffmpeg-h264_cuvid-output-corrupt"
packets_requested = $activeFrameCount
frames_decoded = $decodedCount
repaired_frame_count = $repairs.Count
repairs = $repairs
}
$decodeRepair | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath $decodeRepairPath -Encoding utf8
$firstPacketPts = [int64]$packetPts[0]
$previousEpochSeconds = -1.0
$timelineWriter = [IO.StreamWriter]::new($timelinePath, $false, [Text.UTF8Encoding]::new($false))
try {
for ($index = 0; $index -lt $activeFrameCount; $index++) {
$epochSeconds = [double]::Parse(
([string]$pts[$index].best_effort_timestamp_time).Trim(),
[Globalization.CultureInfo]::InvariantCulture
) - $firstEpochSeconds
$epochSeconds = ([int64]$packetPts[$index] - $firstPacketPts) / 90000.0
if ($epochSeconds -le $previousEpochSeconds -or $epochSeconds -gt ($timelineDuration + 0.001)) {
throw "Decoded LAB E4 timestamps are not strictly monotonic inside the camera timeline"
}
@@ -313,6 +356,7 @@ try {
Write-Output ("PHASE=e4-inference-start FRAMES={0}" -f $activeFrameCount)
& docker @runArgs
Assert-LastExitCode "LAB E4 semantic inference"
Copy-Item -LiteralPath $decodeRepairPath -Destination (Join-Path $stagingRoot "decode-repair.json")
$freeBytesPostInference = Assert-FreeSpace "post-inference"
Write-Output "PHASE=e4-inference-complete"