-
Notifications
You must be signed in to change notification settings - Fork 1.7k
210 lines (189 loc) · 8.55 KB
/
Copy pathsync-tests.yml
File metadata and controls
210 lines (189 loc) · 8.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
name: A/V Sync Tests
# Verifies audio/video sync correctness on every platform:
# 1. Unit + property tests for the timestamp pipeline (encoders, drift
# trackers, muxers).
# 2. The synthetic device matrix: fake cameras/screens/microphones across
# frame rates, sample rates, channel counts and delivery pathologies
# (jitter, drops, static-screen gaps), driven through the real recording
# pipeline and verified at the container level. No capture hardware or
# GPU required, so results are deterministic on hosted runners.
#
# Findings are published as a job-summary table and a JSON artifact per OS.
on:
workflow_dispatch:
schedule:
- cron: "0 5 * * *"
pull_request:
paths:
- "crates/recording/**"
- "crates/enc-ffmpeg/**"
- "crates/enc-avfoundation/**"
- "crates/enc-mediafoundation/**"
- "crates/timestamp/**"
- "crates/rendering/**"
- "crates/media-info/**"
- ".github/workflows/sync-tests.yml"
concurrency:
group: sync-tests-${{ github.head_ref || github.ref_name }}
cancel-in-progress: true
permissions:
contents: read
jobs:
sync-tests:
strategy:
fail-fast: false
matrix:
runner:
- macos-latest
- windows-2022
- ubuntu-24.04
runs-on: ${{ matrix.runner }}
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Rust setup
uses: dtolnay/rust-toolchain@1.88.0
- name: Rust cache
uses: ./.github/actions/setup-rust-cache
with:
target: ${{ runner.os == 'Windows' && 'x86_64-pc-windows-msvc' || runner.os == 'macOS' && 'aarch64-apple-darwin' || 'x86_64-unknown-linux-gnu' }}
- name: Install desktop dependencies
uses: ./.github/actions/install-desktop-deps
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 24
- name: Native dependencies
env:
RUST_TARGET_TRIPLE: ${{ runner.os == 'Linux' && 'x86_64-unknown-linux-gnu' || runner.os == 'Windows' && 'x86_64-pc-windows-msvc' || 'aarch64-apple-darwin' }}
run: node scripts/setup.js
- name: Add FFmpeg DLLs to PATH
if: runner.os == 'Windows'
shell: pwsh
run: Add-Content -Path $env:GITHUB_PATH -Value "${{ github.workspace }}\\target\\ffmpeg\\bin"
- name: Install software Vulkan driver (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y mesa-vulkan-drivers libvulkan1
# Hosted Windows runners have no audio endpoint, so WASAPI loopback
# capture (system audio) cannot run at all without a virtual sound
# card. Scream provides a signed null render device; with it installed,
# the loopback keepalive, AUDCLNT_BUFFERFLAGS_SILENT zeroing and QPC
# capture timestamps are exercised against a real audio engine.
#
# Pinned to 3.6: later releases (3.8/4.0) were signed after the 2021
# kernel cross-signing deprecation and PnP blocks their install on an
# interactive consent prompt, which hangs headless runners. The step
# timeout turns any such hang into a fast failure.
- name: Install virtual audio device (Windows)
if: runner.os == 'Windows'
timeout-minutes: 10
shell: pwsh
run: |
Invoke-WebRequest -Uri https://github.com/duncanthrax/scream/releases/download/3.6/Scream3.6.zip -OutFile Scream3.6.zip
$expected = "25ea5e778b4e6995a98d448b9b5f6d321f681663f1aeeec69d8e63183d008b19"
$actual = (Get-FileHash -Algorithm SHA256 Scream3.6.zip).Hash.ToLowerInvariant()
if ($actual -ne $expected) { throw "Scream3.6.zip SHA-256 mismatch: got $actual, expected $expected" }
Expand-Archive -Path Scream3.6.zip -DestinationPath Scream
$cert = (Get-AuthenticodeSignature Scream\Install\driver\Scream.sys).SignerCertificate
$store = [System.Security.Cryptography.X509Certificates.X509Store]::new("TrustedPublisher", "LocalMachine")
$store.Open("ReadWrite")
$store.Add($cert)
$store.Close()
Scream\Install\helpers\devcon.exe install Scream\Install\driver\Scream.inf *Scream
if ($LASTEXITCODE -gt 1) { throw "devcon install failed with exit code $LASTEXITCODE" }
Start-Service -Name Audiosrv -ErrorAction SilentlyContinue
- name: Timestamp pipeline unit + property tests
shell: bash
run: |
cargo test --locked -p cap-timestamp -p cap-enc-ffmpeg
cargo test --locked -p cap-recording --lib
cargo test --locked -p cap-rendering
# The AVFoundation encoder (studio camera/display on macOS) has its own
# pts handling; its fps-matrix duration tests guard against re-timing
# sources that deliver at a different rate than configured.
- name: AVFoundation encoder tests (macOS)
if: runner.os == 'macOS'
shell: bash
run: |
cargo test --locked -p cap-enc-avfoundation
# Runs against the Scream endpoint installed above; the env var turns
# a missing endpoint (driver install regression) into a hard failure
# instead of a silent skip.
- name: WASAPI loopback endpoint tests (Windows)
if: runner.os == 'Windows'
shell: bash
env:
CAP_REQUIRE_AUDIO_ENDPOINT: "1"
run: |
cargo test --locked -p cap-recording --test windows_loopback -- --nocapture
- name: Synthetic device matrix
id: matrix
continue-on-error: true
shell: bash
env:
CAP_SYNC_MATRIX_REPORT: ${{ github.workspace }}/sync-matrix-${{ matrix.runner }}.json
CAP_SYNC_MATRIX_RANDOM_CASES: ${{ github.event_name == 'schedule' && '40' || '6' }}
run: |
cargo test --locked -p cap-recording --test sync_matrix -- --nocapture
# Verifies the editor's playback machinery (decoders, frame scheduling,
# audio pipeline) preserves sync. The fixture recording is generated
# through the real recording pipeline, so no capture hardware is needed;
# rendering uses the platform's software adapter where no GPU exists.
# 30s of pattern stabilizes the drift slope against frame-quantization
# noise. Playback runs at the default 30 fps: lower rates trip the audio
# sync policy's drift-correction threshold every few frames and accrue
# real (policy-induced) drift that fails the gate.
#
# Linux-only: the Windows WARP adapter composites blank frames and the
# macOS runners' paravirtualized Metal collapses to ~2 fps presentation
# regardless of decoder, so neither can sustain a wall-clock playback
# measurement. The decoder logic under test (FFmpeg gap holds) is fully
# exercised here; the macOS AVAssetReader path is covered by running
# `cap selftest playback` locally on real hardware.
- name: Editor playback sync harness
if: runner.os == 'Linux'
shell: bash
run: |
cargo run --locked -p cap -- --log-level info selftest playback --duration 30 --json
- name: Report findings
if: always()
shell: bash
run: |
REPORT="${{ github.workspace }}/sync-matrix-${{ matrix.runner }}.json"
{
echo "## A/V sync matrix — ${{ matrix.runner }}"
echo ""
if [ -f "$REPORT" ]; then
PYTHONIOENCODING=utf-8 python3 - "$REPORT" << 'PYEOF'
import json, sys
report = json.load(open(sys.argv[1]))
print(f"Randomized seed: `{report.get('seed')}` (rerun with CAP_SYNC_MATRIX_SEED)")
print()
print("| Case | Result | Detail |")
print("| --- | --- | --- |")
for case in report.get("cases", []):
verdict = "PASS" if case["pass"] else "FAIL"
detail = case["detail"].replace("|", "\\|")
print(f"| {case['name']} | {verdict} | {detail} |")
PYEOF
else
echo "No report produced — the matrix crashed before writing results."
fi
} >> "$GITHUB_STEP_SUMMARY"
- name: Upload findings
if: always()
uses: actions/upload-artifact@v4
with:
name: sync-matrix-${{ matrix.runner }}
path: ${{ github.workspace }}/sync-matrix-${{ matrix.runner }}.json
if-no-files-found: ignore
- name: Fail on matrix failures
if: steps.matrix.outcome == 'failure'
shell: bash
run: |
echo "Synthetic sync matrix reported failures; see the job summary." >&2
exit 1