speaker-verification
audio
nemotron
tyger
experimental
File size: 6,623 Bytes
b21cfae
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0efd0f1
 
 
 
 
 
b21cfae
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0efd0f1
 
 
b21cfae
 
 
 
 
 
 
 
 
 
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
"""Real Chromium, fake media/network: startup, cancellation and mic privacy.

Run with Playwright installed, e.g.:
uv run --no-project --with playwright python browser_lifecycle_checks.py
No GPU, hosted API, physical microphone, camera or real WebSocket is used.
"""
from functools import partial
import http.server
import json
import os
from pathlib import Path
import threading

from playwright.sync_api import sync_playwright


class QuietHandler(http.server.SimpleHTTPRequestHandler):
    def log_message(self, *_args):
        pass


CHECKS = r"""async () => {
  const {RoboClient} = await import('/client.js');
  const realWS = window.WebSocket;
  const realGUM = navigator.mediaDevices.getUserMedia;
  const sockets = [];
  const results = [];
  const tick = () => new Promise(r => setTimeout(r, 0));
  const assert = (yes, text) => { if (!yes) throw Error(text); };
  function context(addModule = async () => {}) {
    return {audioWorklet: {addModule}, close: async () => {},
      createMediaStreamSource: () => ({connect() {}, disconnect() {}})};
  }
  function client(addModule) {
    const c = new RoboClient();
    c.ctx = context(addModule);
    c.clock = {stop() {}, inputLatency: null};
    return c;
  }
  function media() {
    let stopped = 0;
    const track = {stop() { stopped++; }, getSettings() { return {}; }};
    return {stream: {getTracks: () => [track], getAudioTracks: () => [track]},
      get stopped() { return stopped; }};
  }
  class FakeWS {
    constructor() {
      this.readyState = 0; sockets.push(this);
      setTimeout(() => { if (this.readyState === 0) {
        this.readyState = 1; this.onopen?.();
      }}, 15);
    }
    close() { this.readyState = 3; this.onclose?.(); }
    send() {}
  }
  try {
    window.WebSocket = FakeWS;

    const c = client();
    const before = sockets.length;
    await Promise.all([c.start(false), c.start(false), c.start(false)]);
    assert(sockets.length-before === 1, 'Concurrent start opened multiple sockets');
    c.stop(); results.push('concurrent_start_uses_one_websocket');

    const failedMedia = media();
    navigator.mediaDevices.getUserMedia = async () => failedMedia.stream;
    const f = client(async () => { throw Error('Injected worklet loading failure'); });
    let failed = false;
    try { await f.start(true); } catch { failed = true; }
    assert(failed, 'Injected worklet failure did not reject');
    assert(failedMedia.stopped >= 1 && f.stream === null && f.ctx === null,
      'Microphone leaked after worklet failure');
    results.push('worklet_failure_stops_microphone');

    let resolveLate;
    const late = media();
    navigator.mediaDevices.getUserMedia = () => new Promise(r => { resolveLate = r; });
    const l = client();
    const pending = l.start(true).then(() => false, () => true);
    await tick(); l.stop(); resolveLate(late.stream);
    assert(await pending, 'Stopped startup unexpectedly succeeded');
    assert(late.stopped >= 1 && l.stream === null && l.ctx === null,
      'Late media permission left microphone running');
    results.push('late_get_user_media_after_stop_is_released');

    let resolveOld;
    const oldMedia = media();
    navigator.mediaDevices.getUserMedia = () => new Promise(r => { resolveOld = r; });
    const r = client();
    const oldStart = r.start(true).then(() => false, () => true);
    await tick(); r.stop();
    const newContext = context(); r.ctx = newContext; r.clock = {stop() {}};
    await r.start(false); const newSocket = r.ws;
    resolveOld(oldMedia.stream); await oldStart;
    assert(oldMedia.stopped >= 1 && r.ws === newSocket && r.ctx === newContext,
      'Cancelled old media startup damaged the new conversation');
    r.stop(); results.push('old_media_result_cannot_close_new_session');

    const s = client(); await s.start(false); const oldSocket = s.ws;
    s.stop(); s.ctx = context(); s.clock = {stop() {}};
    await s.start(false); const currentSocket = s.ws;
    oldSocket.onclose();
    assert(s.ws === currentSocket && currentSocket.readyState === 1,
      'Stale close callback stopped a new WebSocket');
    s.stop(); results.push('stale_websocket_close_is_ignored');

    const resumed = client();let resumes=0;
    resumed.ctx.state='suspended';resumed.ctx.resume=async()=>{resumes++;resumed.ctx.state='running';};
    await resumed.start(false);
    assert(resumes===1 && resumed.ctx.state==='running','Existing suspended context did not resume');
    resumed.stop();results.push('existing_suspended_audio_context_resumes');

    let resolveModule;
    const workletMedia = media();
    navigator.mediaDevices.getUserMedia = async () => workletMedia.stream;
    const w = client(() => new Promise(r => { resolveModule = r; }));
    const workletStart = w.start(true).then(() => false, () => true);
    await tick(); w.stop(); resolveModule(); await workletStart;
    assert(workletMedia.stopped >= 1 && w.stream === null && w.ctx === null,
      'Stopped pending worklet reattached a microphone');
    results.push('late_worklet_cannot_reattach_microphone');

    return {passed: results.length, checks: results,
      physical_microphone_used: false, hosted_api_calls: 0, real_websockets: 0};
  } finally {
    window.WebSocket = realWS;
    navigator.mediaDevices.getUserMedia = realGUM;
  }
}"""


def main():
    static = Path(__file__).resolve().parent / 'static'
    server = http.server.ThreadingHTTPServer(('127.0.0.1', 0),
        partial(QuietHandler, directory=str(static)))
    threading.Thread(target=server.serve_forever, daemon=True).start()
    try:
        with sync_playwright() as p:
            browser = p.chromium.launch(executable_path=os.environ.get(
                'ROBO_CHROME', '/usr/bin/google-chrome'), headless=True,
                args=['--no-sandbox'])
            try:
                page = browser.new_page()
                # A directory index is unnecessary: only establish a secure-local origin.
                page.goto(f'http://127.0.0.1:{server.server_port}/clock.js')
                errors = []
                page.on('pageerror', lambda e: errors.append(str(e)))
                report = page.evaluate(CHECKS)
                assert not errors, errors
                target=Path(__file__).resolve().parent/'logs/browser-lifecycle-checks.json'
                target.parent.mkdir(exist_ok=True)
                target.write_text(json.dumps(report,indent=2))
                print(json.dumps(report, indent=2))
            finally:
                browser.close()
    finally:
        server.shutdown()
        server.server_close()


if __name__ == '__main__':
    main()