@tapflowio/android-agent 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,255 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { fileURLToPath } from 'node:url';
3
+ import path from 'node:path';
4
+ import { createLogger } from '@tapflowio/agent-core';
5
+ const logger = createLogger('android-agent:emulator-video');
6
+ // The Swift VT encoder, two levels up in both src/ (tsx) and dist/ (build).
7
+ const ENCODER_BIN = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', '..', 'bin', 'emulator-encoder');
8
+ /** Detect the baked-in corner radius from an RGBA frame: the rounded corner is exact (0,0,0), so the
9
+ * run of black down the left edge from the top = the radius. Returns a fraction of width (0 = none). */
10
+ export function detectCornerRadius(image, w, h) {
11
+ const isBlack = (x, y) => {
12
+ const o = (y * w + x) * 4;
13
+ return image[o] === 0 && image[o + 1] === 0 && image[o + 2] === 0;
14
+ };
15
+ if (w <= 0 || h <= 0 || !isBlack(0, 0))
16
+ return 0; // square content (e.g. scrcpy) → no rounding
17
+ const cap = Math.floor(w * 0.25); // a radius beyond 25% of width isn't a corner — bail to 0
18
+ let r = 0;
19
+ while (r < cap && isBlack(0, r))
20
+ r++;
21
+ return r >= cap ? 0 : r / w;
22
+ }
23
+ /**
24
+ * The emulator video backend: captures raw RGBA via the emulator's gRPC `streamScreenshot`
25
+ * (bypassing the guest SW encoder), pipes it to the host-side Swift VideoToolbox encoder, and
26
+ * emits the same `{payload, keyframe}` H.264 frames as `ScrcpyVideo` so the agent pump is
27
+ * backend-agnostic. Input is handled separately via `EmulatorGrpcClient`.
28
+ */
29
+ export class EmulatorVideo {
30
+ client;
31
+ options;
32
+ encoder = null;
33
+ capture = null;
34
+ controller = null;
35
+ buffered = [];
36
+ stdoutBuf = Buffer.alloc(0);
37
+ width = 0;
38
+ height = 0;
39
+ stopped = false;
40
+ outputClosed = false;
41
+ encoderBusy = false; // encoder stdin is saturated → drop frames until 'drain' (no unbounded buffering)
42
+ flushTimer = null;
43
+ constructor(client, options = {}) {
44
+ this.client = client;
45
+ this.options = options;
46
+ }
47
+ /** Spawns the encoder and starts capture; resolves once the first frame fixes the dimensions. */
48
+ async start() {
49
+ const fps = this.options.fps ?? 30;
50
+ const spawnEncoder = this.options.spawnEncoder ?? ((f) => spawn(ENCODER_BIN, [String(f)]));
51
+ this.encoder = spawnEncoder(fps);
52
+ this.encoder.stderr.on('data', (d) => logger.info(`encoder: ${d.toString().trim()}`));
53
+ this.encoder.stdout.on('data', (chunk) => this.onEncoderOutput(chunk));
54
+ // Writes racing teardown (the encoder is killed while the pump still has a frame) surface as
55
+ // EPIPE on stdin; without a handler that's an uncaught error that crashes the agent.
56
+ this.encoder.stdin.on('error', (e) => { if (!this.stopped)
57
+ logger.warn(`encoder stdin: ${e.message}`); });
58
+ this.capture = this.client.streamScreenshot({ width: this.options.maxWidth ?? 0, height: this.options.maxHeight ?? 0 });
59
+ // Pump raw frames into the encoder; the first one fixes the reported size. start() rejects if the
60
+ // capture errors (e.g. auth failure) OR the encoder dies before any frame — either way the caller
61
+ // falls back to scrcpy instead of being left with a silently dead stream.
62
+ return new Promise((resolve, reject) => {
63
+ let settled = false;
64
+ const ok = (info) => { if (!settled) {
65
+ settled = true;
66
+ resolve(info);
67
+ } };
68
+ const fail = (e) => { if (!settled) {
69
+ settled = true;
70
+ reject(e);
71
+ } };
72
+ const onDead = (msg) => { if (this.stopped)
73
+ return; logger.warn(msg); fail(new Error(msg)); };
74
+ this.encoder.on('exit', (code) => onDead(`encoder exited (${code})`));
75
+ this.encoder.on('error', (e) => onDead(`encoder process: ${e.message}`));
76
+ void this.pump(ok, fail);
77
+ });
78
+ }
79
+ async pump(onFirst, onError) {
80
+ // Cap to target fps: the source streams up to 60fps under motion, but LAN-HTTP (WASM decode)
81
+ // wants iOS-parity 30fps to halve decode/transport/bandwidth. The first frame (IDR) always
82
+ // goes through; -2ms tolerates source jitter so 60→30 doesn't accidentally drop to 20.
83
+ const minIntervalMs = 1000 / (this.options.fps ?? 30) - 2;
84
+ let lastFwdMs = 0;
85
+ let pendingFrame = null;
86
+ let first = true;
87
+ let captureError;
88
+ try {
89
+ for await (const f of this.capture.frames) {
90
+ if (this.stopped)
91
+ break;
92
+ if (f.width !== this.width || f.height !== this.height) {
93
+ this.width = f.width;
94
+ this.height = f.height;
95
+ logger.info(`video size → ${f.width}×${f.height}`);
96
+ }
97
+ const now = performance.now();
98
+ if (!first && now - lastFwdMs < minIntervalMs) {
99
+ // Throttled: hold the latest frame and flush it at the interval boundary if nothing newer
100
+ // arrives. The source is frame-driven (no frames while static), so a plain drop would lose
101
+ // the final update of a small change → the viewer freezes on the pre-change frame.
102
+ pendingFrame = f;
103
+ if (!this.flushTimer) {
104
+ this.flushTimer = setTimeout(() => {
105
+ this.flushTimer = null;
106
+ if (pendingFrame && !this.stopped) {
107
+ lastFwdMs = performance.now();
108
+ this.writeToEncoder(pendingFrame.image, pendingFrame.width, pendingFrame.height);
109
+ pendingFrame = null;
110
+ }
111
+ }, minIntervalMs - (now - lastFwdMs));
112
+ this.flushTimer.unref?.();
113
+ }
114
+ continue;
115
+ }
116
+ if (this.flushTimer) {
117
+ clearTimeout(this.flushTimer);
118
+ this.flushTimer = null;
119
+ }
120
+ pendingFrame = null;
121
+ lastFwdMs = now;
122
+ if (first) {
123
+ first = false;
124
+ onFirst({ width: f.width, height: f.height, cornerRadius: detectCornerRadius(f.image, f.width, f.height) });
125
+ }
126
+ this.writeToEncoder(f.image, f.width, f.height);
127
+ }
128
+ }
129
+ catch (e) {
130
+ captureError = e;
131
+ if (!this.stopped) {
132
+ logger.warn(`capture ended: ${captureError.message}`);
133
+ // The emulator's default gRPC port requires a token; only an agent-launched `-grpc <port>`
134
+ // endpoint is unsecured. A reused, externally-booted emulator (or one missing -grpc) hits this.
135
+ if (captureError.message.includes('UNAUTHENTICATED')) {
136
+ logger.error('emulator gRPC requires auth — relaunch it via the agent so it gets `-grpc <port>` (unsecured localhost), or shut down the externally-booted emulator first.');
137
+ }
138
+ }
139
+ }
140
+ if (this.flushTimer) {
141
+ clearTimeout(this.flushTimer);
142
+ this.flushTimer = null;
143
+ }
144
+ // Settle start()'s promise: reject on a pre-first-frame error (→ scrcpy fallback), else resolve
145
+ // (a clean early end, e.g. stopped during boot, reports the last-known dims).
146
+ if (first) {
147
+ if (captureError)
148
+ onError(captureError);
149
+ else
150
+ onFirst({ width: this.width, height: this.height, cornerRadius: 0 });
151
+ }
152
+ // Source ended (cancelled / emulator gone) — settle the output stream.
153
+ this.closeOutput();
154
+ }
155
+ // Settle the output stream once. Set the flag *before* closing so a late encoder stdout chunk
156
+ // (the encoder process flushes asynchronously) is dropped by emit() instead of enqueuing onto a
157
+ // closed controller (which throws ERR_INVALID_STATE and would crash the agent).
158
+ closeOutput() {
159
+ if (this.outputClosed)
160
+ return;
161
+ this.outputClosed = true;
162
+ try {
163
+ this.controller?.close();
164
+ }
165
+ catch { /* already closed */ }
166
+ }
167
+ writeToEncoder(rgba, w, h) {
168
+ if (this.stopped)
169
+ return;
170
+ const stdin = this.encoder?.stdin;
171
+ if (!stdin || stdin.destroyed)
172
+ return;
173
+ // Backpressure: the encoder is behind. Drop this frame rather than queue another ~12MB RGBA
174
+ // buffer in Node's stdin (which would balloon memory at 30fps). Resume once it drains.
175
+ if (this.encoderBusy)
176
+ return;
177
+ const hdr = Buffer.allocUnsafe(13);
178
+ hdr[0] = 0x00;
179
+ hdr.writeUInt32BE(w, 1);
180
+ hdr.writeUInt32BE(h, 5);
181
+ hdr.writeUInt32BE(rgba.length, 9);
182
+ stdin.write(hdr);
183
+ if (!stdin.write(rgba)) {
184
+ this.encoderBusy = true;
185
+ stdin.once('drain', () => { this.encoderBusy = false; });
186
+ }
187
+ }
188
+ // Length-delimited Annex B from the encoder: [len:u32][flags:u8][payload]; flags bit0 = keyframe.
189
+ onEncoderOutput(chunk) {
190
+ this.stdoutBuf = Buffer.concat([this.stdoutBuf, chunk]);
191
+ while (this.stdoutBuf.length >= 4) {
192
+ const len = this.stdoutBuf.readUInt32BE(0);
193
+ if (this.stdoutBuf.length < 4 + len)
194
+ break;
195
+ const flags = this.stdoutBuf[4];
196
+ const payload = Buffer.from(this.stdoutBuf.subarray(5, 4 + len));
197
+ this.stdoutBuf = this.stdoutBuf.subarray(4 + len);
198
+ this.emit({ payload, keyframe: (flags & 1) === 1 });
199
+ }
200
+ }
201
+ emit(frame) {
202
+ if (this.outputClosed)
203
+ return;
204
+ if (this.controller) {
205
+ try {
206
+ this.controller.enqueue(frame);
207
+ }
208
+ catch {
209
+ this.outputClosed = true;
210
+ }
211
+ }
212
+ else {
213
+ this.buffered.push(frame);
214
+ }
215
+ }
216
+ /** H.264 access units, contract-compatible with `ScrcpyVideo.start()`. */
217
+ frames() {
218
+ return new ReadableStream({
219
+ start: (controller) => {
220
+ this.controller = controller;
221
+ for (const f of this.buffered)
222
+ controller.enqueue(f);
223
+ this.buffered.length = 0;
224
+ },
225
+ cancel: () => this.stop(),
226
+ });
227
+ }
228
+ /** Relay drop-to-keyframe / join recovery: force the encoder to re-emit an IDR. */
229
+ requestIdr() {
230
+ if (this.stopped)
231
+ return;
232
+ const stdin = this.encoder?.stdin;
233
+ if (stdin && !stdin.destroyed)
234
+ stdin.write(Buffer.from([0x01]));
235
+ }
236
+ stop() {
237
+ if (this.stopped)
238
+ return;
239
+ this.stopped = true;
240
+ if (this.flushTimer) {
241
+ clearTimeout(this.flushTimer);
242
+ this.flushTimer = null;
243
+ }
244
+ this.closeOutput();
245
+ this.capture?.cancel();
246
+ if (this.encoder) {
247
+ // Drop late stdout so it can't enqueue after teardown.
248
+ this.encoder.stdout.removeAllListeners('data');
249
+ this.encoder.stdin.end();
250
+ this.encoder.kill();
251
+ this.encoder = null;
252
+ }
253
+ }
254
+ }
255
+ //# sourceMappingURL=EmulatorVideo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EmulatorVideo.js","sourceRoot":"","sources":["../../src/emulator/EmulatorVideo.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ScrcpyVideo.d.ts","sourceRoot":"","sources":["../../src/scrcpy/ScrcpyVideo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,KAAK,CAAA;AAoBjC,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED;oEACoE;AACpE,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,2DAA2D;IAC3D,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,qBAAa,WAAW;IAeV,OAAO,CAAC,QAAQ,CAAC,MAAM;IAdnC,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAC/C,OAAO,CAAC,aAAa,CAAkD;IACvE,OAAO,CAAC,YAAY,CAAoC;IACxD,OAAO,CAAC,gBAAgB,CAA4D;IACpF,OAAO,CAAC,OAAO,CAAkB;IAIjC,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,cAAc,CAAQ;IAC9B,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,aAAa,CAAQ;gBAEA,MAAM,EAAE,MAAM;IAa3C,OAAO,CAAC,MAAM;IAcd,UAAU,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAQvC,KAAK,IAAI,cAAc,CAAC,WAAW,CAAC;IAepC,OAAO,CAAC,MAAM;IAkBd,OAAO,CAAC,YAAY;IAyBpB,OAAO,CAAC,IAAI;IAKZ,OAAO,CAAC,WAAW;CAUpB"}
1
+ {"version":3,"file":"ScrcpyVideo.d.ts","sourceRoot":"","sources":["../../src/scrcpy/ScrcpyVideo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,KAAK,CAAA;AAoBjC,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED;oEACoE;AACpE,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,2DAA2D;IAC3D,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,qBAAa,WAAW;IAeV,OAAO,CAAC,QAAQ,CAAC,MAAM;IAdnC,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAC/C,OAAO,CAAC,aAAa,CAAkD;IACvE,OAAO,CAAC,YAAY,CAAoC;IACxD,OAAO,CAAC,gBAAgB,CAA4D;IACpF,OAAO,CAAC,OAAO,CAAkB;IAIjC,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,cAAc,CAAQ;IAC9B,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,aAAa,CAAQ;gBAEA,MAAM,EAAE,MAAM;IAa3C,OAAO,CAAC,MAAM;IAkBd,UAAU,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAQvC,KAAK,IAAI,cAAc,CAAC,WAAW,CAAC;IAkBpC,OAAO,CAAC,MAAM;IAkBd,OAAO,CAAC,YAAY;IAyBpB,OAAO,CAAC,IAAI;IAKZ,OAAO,CAAC,WAAW;CAUpB"}
@@ -54,10 +54,15 @@ export class ScrcpyVideo {
54
54
  }
55
55
  if (!this.streamController)
56
56
  return; // start() will close once it observes endReceived
57
- if (err)
58
- this.streamController.error(err);
59
- else
60
- this.streamController.close();
57
+ // The controller may already be closed (e.g. a late socket event after another
58
+ // settle path) — closing/erroring twice throws, so swallow it.
59
+ try {
60
+ if (err)
61
+ this.streamController.error(err);
62
+ else
63
+ this.streamController.close();
64
+ }
65
+ catch { /* already closed */ }
61
66
  }
62
67
  deviceInfo() {
63
68
  if (this.headerBuf)
@@ -79,6 +84,9 @@ export class ScrcpyVideo {
79
84
  controller.close();
80
85
  },
81
86
  cancel: () => {
87
+ // The consumer cancelled — the stream is already settled by the ReadableStream
88
+ // itself, so the socket 'close'/'error' that destroy() triggers must not re-close it.
89
+ this.streamSettled = true;
82
90
  this.socket.destroy();
83
91
  },
84
92
  });
@@ -1 +1 @@
1
- {"version":3,"file":"ScrcpyVideo.js","sourceRoot":"","sources":["../../src/scrcpy/ScrcpyVideo.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ScrcpyVideo.js","sourceRoot":"","sources":["../../src/scrcpy/ScrcpyVideo.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tapflowio/android-agent",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Android emulator agent for tapflow — ADB control and scrcpy H.264 streaming",
5
5
  "keywords": [
6
6
  "tapflow",
@@ -35,6 +35,7 @@
35
35
  "files": [
36
36
  "dist",
37
37
  "bin",
38
+ "proto",
38
39
  "README.md",
39
40
  "LICENSE"
40
41
  ],
@@ -45,15 +46,17 @@
45
46
  "access": "public"
46
47
  },
47
48
  "dependencies": {
49
+ "@grpc/grpc-js": "^1.14.4",
50
+ "@grpc/proto-loader": "^0.8.1",
48
51
  "ws": "^8.0.0",
49
- "@tapflowio/agent-core": "0.6.0"
52
+ "@tapflowio/agent-core": "0.7.0"
50
53
  },
51
54
  "devDependencies": {
52
55
  "@types/node": "^20.0.0",
53
56
  "@types/ws": "^8.0.0",
54
57
  "typescript": "^5.0.0",
55
- "vitest": "^2.0.0",
56
- "@tapflowio/relay": "0.6.0"
58
+ "vitest": "^4.1.8",
59
+ "@tapflowio/relay": "0.7.0"
57
60
  },
58
61
  "scripts": {
59
62
  "build": "tsc",