appium-ios-remotexpc 5.14.0 → 5.14.1

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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## [5.14.1](https://github.com/appium/appium-ios-remotexpc/compare/v5.14.0...v5.14.1) (2026-08-11)
2
+
3
+ ### Bug Fixes
4
+
5
+ * **display:** surface screen-recording write errors instead of crashing ([#289](https://github.com/appium/appium-ios-remotexpc/issues/289)) ([2ef7852](https://github.com/appium/appium-ios-remotexpc/commit/2ef7852814d01bcc08202e82434ebea74424d8de))
6
+
1
7
  ## [5.14.0](https://github.com/appium/appium-ios-remotexpc/compare/v5.13.6...v5.14.0) (2026-08-09)
2
8
 
3
9
  ### Features
@@ -1 +1 @@
1
- {"version":3,"file":"av-capture.d.ts","sourceRoot":"","sources":["../../../../../../src/services/ios/display/recording/av-capture.ts"],"names":[],"mappings":"AAKA,OAAO,EAAC,KAAK,YAAY,EAAmB,MAAM,qBAAqB,CAAC;AACxE,OAAO,EAAqB,KAAK,gBAAgB,EAAC,MAAM,kCAAkC,CAAC;AAE3F,OAAO,EAAC,KAAK,cAAc,EAAE,KAAK,uBAAuB,EAAC,MAAM,aAAa,CAAC;AAE9E,OAAO,EAAsB,KAAK,iBAAiB,EAAC,MAAM,mCAAmC,CAAC;AAC9F,OAAO,EAAC,KAAK,UAAU,EAA0B,MAAM,kBAAkB,CAAC;AAI1E,uDAAuD;AACvD,MAAM,WAAW,2BAA4B,SAAQ,uBAAuB;IAC1E,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,yDAAyD;AACzD,MAAM,WAAW,0BAA0B;IACzC,uBAAuB;IACvB,KAAK,EAAE;QACL,uDAAuD;QACvD,IAAI,EAAE,MAAM,CAAC;QACb,qCAAqC;QACrC,aAAa,EAAE,MAAM,CAAC;QACtB,qBAAqB;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,0EAA0E;QAC1E,UAAU,EAAE,MAAM,CAAC;QACnB;;;;;;WAMG;QACH,SAAS,EAAE,MAAM,CAAC;QAClB,mEAAmE;QACnE,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,wBAAwB;QACxB,KAAK,EAAE,iBAAiB,CAAC;KAC1B,CAAC;IACF,uBAAuB;IACvB,KAAK,EAAE;QACL,oCAAoC;QACpC,IAAI,EAAE,MAAM,CAAC;QACb,4BAA4B;QAC5B,kBAAkB,EAAE,MAAM,CAAC;QAC3B,qBAAqB;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB;;;;;WAKG;QACH,UAAU,EAAE,MAAM,CAAC;QACnB,iCAAiC;QACjC,MAAM,EAAE,YAAY,CAAC;QACrB,wBAAwB;QACxB,KAAK,EAAE,gBAAgB,CAAC;KACzB,CAAC;IACF;;;;;;;OAOG;IACH,UAAU,EAAE,UAAU,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,0BAA0B,CAAC,CAkHrC"}
1
+ {"version":3,"file":"av-capture.d.ts","sourceRoot":"","sources":["../../../../../../src/services/ios/display/recording/av-capture.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,KAAK,YAAY,EAAmB,MAAM,qBAAqB,CAAC;AACxE,OAAO,EAAqB,KAAK,gBAAgB,EAAC,MAAM,kCAAkC,CAAC;AAE3F,OAAO,EAAC,KAAK,cAAc,EAAE,KAAK,uBAAuB,EAAC,MAAM,aAAa,CAAC;AAE9E,OAAO,EAAwC,KAAK,iBAAiB,EAAC,MAAM,mCAAmC,CAAC;AAChH,OAAO,EAAC,KAAK,UAAU,EAA0B,MAAM,kBAAkB,CAAC;AAI1E,uDAAuD;AACvD,MAAM,WAAW,2BAA4B,SAAQ,uBAAuB;IAC1E,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,yDAAyD;AACzD,MAAM,WAAW,0BAA0B;IACzC,uBAAuB;IACvB,KAAK,EAAE;QACL,uDAAuD;QACvD,IAAI,EAAE,MAAM,CAAC;QACb,qCAAqC;QACrC,aAAa,EAAE,MAAM,CAAC;QACtB,qBAAqB;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,0EAA0E;QAC1E,UAAU,EAAE,MAAM,CAAC;QACnB;;;;;;WAMG;QACH,SAAS,EAAE,MAAM,CAAC;QAClB,mEAAmE;QACnE,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,wBAAwB;QACxB,KAAK,EAAE,iBAAiB,CAAC;KAC1B,CAAC;IACF,uBAAuB;IACvB,KAAK,EAAE;QACL,oCAAoC;QACpC,IAAI,EAAE,MAAM,CAAC;QACb,4BAA4B;QAC5B,kBAAkB,EAAE,MAAM,CAAC;QAC3B,qBAAqB;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB;;;;;WAKG;QACH,UAAU,EAAE,MAAM,CAAC;QACnB,iCAAiC;QACjC,MAAM,EAAE,YAAY,CAAC;QACrB,wBAAwB;QACxB,KAAK,EAAE,gBAAgB,CAAC;KACzB,CAAC;IACF;;;;;;;OAOG;IACH,UAAU,EAAE,UAAU,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,0BAA0B,CAAC,CAwGrC"}
@@ -1,12 +1,10 @@
1
- import { once } from 'node:events';
2
- import { createWriteStream } from 'node:fs';
3
1
  import { getLogger } from '../../../../lib/logger.js';
4
2
  import { XPCUUID } from '../../../../lib/remote-xpc/xpc-uuid.js';
5
3
  import { aacEldDurationMs } from '../audio/aac-eld.js';
6
4
  import { AudioStreamCapture } from '../audio/audio-stream-capture.js';
7
5
  import { M4aFileWriter } from '../audio/m4a-writer.js';
8
6
  import { toAnnexB } from '../video/hevc.js';
9
- import { ScreenStreamCapture } from '../video/screen-stream-capture.js';
7
+ import { AnnexBFileWriter, ScreenStreamCapture } from '../video/screen-stream-capture.js';
10
8
  import { ffmpegMuxCommandBuilder } from './mux-command.js';
11
9
  const log = getLogger('AvCapture');
12
10
  /**
@@ -52,7 +50,7 @@ export async function recordScreenAndAudioToFiles(service, options) {
52
50
  await videoCapture.stop().catch(() => undefined);
53
51
  throw error;
54
52
  }
55
- const videoOut = createWriteStream(videoPath);
53
+ const videoOut = new AnnexBFileWriter(videoPath);
56
54
  const audioOut = await M4aFileWriter.create(audioPath);
57
55
  let framesWritten = 0;
58
56
  let videoBytes = 0;
@@ -70,9 +68,7 @@ export async function recordScreenAndAudioToFiles(service, options) {
70
68
  sawKeyFrame = true;
71
69
  }
72
70
  const chunk = toAnnexB(unit.nals);
73
- if (!videoOut.write(chunk)) {
74
- await once(videoOut, 'drain');
75
- }
71
+ await videoOut.write(chunk);
76
72
  framesWritten += 1;
77
73
  videoBytes += chunk.length;
78
74
  }
@@ -102,15 +98,7 @@ export async function recordScreenAndAudioToFiles(service, options) {
102
98
  });
103
99
  await audioCapture.stop().catch(() => undefined);
104
100
  audioWritten = await audioOut.close();
105
- await new Promise((resolve, reject) => {
106
- videoOut.end((error) => {
107
- if (error) {
108
- reject(error);
109
- return;
110
- }
111
- resolve();
112
- });
113
- });
101
+ await videoOut.close();
114
102
  }
115
103
  const audioDurationMs = aacEldDurationMs(audioWritten.sampleCount);
116
104
  // Measure against the video's own capture window, never the audio clock: if
@@ -1 +1 @@
1
- {"version":3,"file":"av-capture.js","sourceRoot":"","sources":["../../../../../../src/services/ios/display/recording/av-capture.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"av-capture.js","sourceRoot":"","sources":["../../../../../../src/services/ios/display/recording/av-capture.ts"],"names":[],"mappings":"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"}
@@ -98,6 +98,39 @@ export declare class ScreenStreamCapture {
98
98
  */
99
99
  private consume;
100
100
  }
101
+ /**
102
+ * The Annex-B output file, with the write stream's `'error'` event held instead
103
+ * of left to reach the process.
104
+ *
105
+ * A recording runs unattended for minutes and the stream never escapes the
106
+ * function that owns it, so a caller cannot attach a listener of its own.
107
+ * Without one here, a mistyped path or a write that fails after the fact (a full
108
+ * disk, an unplugged volume) arrives as an uncaught `'error'` event and takes
109
+ * the process down — `end(callback)` does not help, since the callback receives
110
+ * the error *and* the event is still emitted. Holding the first error and
111
+ * re-throwing it from the next `write` or `close` turns that into a rejection
112
+ * the caller can see, the guarantee {@link M4aFileWriter} already gives the
113
+ * audio track.
114
+ *
115
+ * Opening is deliberately not awaited, unlike `M4aFileWriter.create`: the
116
+ * capture is already streaming by the time the file is created, so a rejection
117
+ * before the caller holds the writer would strand it. An open failure surfaces
118
+ * from the first {@link write} instead.
119
+ */
120
+ export declare class AnnexBFileWriter {
121
+ private readonly stream;
122
+ /** First stream error seen, re-thrown from the next `write` or `close`. */
123
+ private streamError;
124
+ /** @param path Destination file path; truncated if it exists. */
125
+ constructor(path: string);
126
+ /**
127
+ * Appends one chunk, resolving once the stream has room for more so an
128
+ * `await` per chunk applies backpressure.
129
+ */
130
+ write(chunk: Buffer): Promise<void>;
131
+ /** Flushes and closes the file, re-throwing any error the stream saw. */
132
+ close(): Promise<void>;
133
+ }
101
134
  /** Options for {@link recordScreenToFile}. */
102
135
  export interface RecordScreenOptions extends ScreenStreamCaptureOptions {
103
136
  /** How long to record, in milliseconds. Defaults to 5000. */
@@ -1 +1 @@
1
- {"version":3,"file":"screen-stream-capture.d.ts","sourceRoot":"","sources":["../../../../../../src/services/ios/display/video/screen-stream-capture.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,cAAc,EAAE,iBAAiB,EAAE,uBAAuB,EAAC,MAAM,aAAa,CAAC;AAG5F,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACrB,MAAM,4BAA4B,CAAC;AAGpC,YAAY,EAAC,iBAAiB,EAAE,iBAAiB,EAAE,eAAe,EAAC,CAAC;AAIpE,qDAAqD;AACrD,MAAM,WAAW,0BAA2B,SAAQ,uBAAuB;IACzE,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,mBAAmB;IAkB5B,QAAQ,CAAC,MAAM,EAAE,iBAAiB;IAjBpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IACzC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmB;IAC5C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6B;IACvD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAyB;IACzD,wEAAwE;IACxE,OAAO,CAAC,SAAS,CAA4B;IAE7C;;;;OAIG;IACH,OAAO,CAAC,WAAW,CAA4B;IAE/C,OAAO;IASP;;;;;;;;OAQG;WACU,KAAK,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,GAAE,0BAA+B,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAuBnH,+EAA+E;IAC/E,IAAI,aAAa,IAAI,iBAAiB,GAAG,SAAS,CAEjD;IAED;;;OAGG;IACH,IAAI,WAAW,IAAI,MAAM,GAAG,SAAS,CAEpC;IAED;;;OAGG;IACH,IAAI,0BAA0B,IAAI,MAAM,GAAG,SAAS,CAEnD;IAED,0CAA0C;IAC1C,IAAI,KAAK,IAAI,iBAAiB,CAE7B;IAED;;;;OAIG;IACI,WAAW,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,cAAc,CAAC,eAAe,EAAE,IAAI,EAAE,OAAO,CAAC;IAexF;;;;;;;OAOG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAKb,QAAQ;IAQtB;;;OAGG;IACH,OAAO,CAAC,OAAO;CAQhB;AAED,8CAA8C;AAC9C,MAAM,WAAW,mBAAoB,SAAQ,0BAA0B;IACrE,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,gDAAgD;AAChD,MAAM,WAAW,kBAAkB;IACjC,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,qBAAqB;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,KAAK,EAAE,iBAAiB,CAAC;CAC1B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,kBAAkB,CAAC,CA4D7B"}
1
+ {"version":3,"file":"screen-stream-capture.d.ts","sourceRoot":"","sources":["../../../../../../src/services/ios/display/video/screen-stream-capture.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,cAAc,EAAE,iBAAiB,EAAE,uBAAuB,EAAC,MAAM,aAAa,CAAC;AAG5F,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACrB,MAAM,4BAA4B,CAAC;AAGpC,YAAY,EAAC,iBAAiB,EAAE,iBAAiB,EAAE,eAAe,EAAC,CAAC;AAIpE,qDAAqD;AACrD,MAAM,WAAW,0BAA2B,SAAQ,uBAAuB;IACzE,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,mBAAmB;IAkB5B,QAAQ,CAAC,MAAM,EAAE,iBAAiB;IAjBpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IACzC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmB;IAC5C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6B;IACvD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAyB;IACzD,wEAAwE;IACxE,OAAO,CAAC,SAAS,CAA4B;IAE7C;;;;OAIG;IACH,OAAO,CAAC,WAAW,CAA4B;IAE/C,OAAO;IASP;;;;;;;;OAQG;WACU,KAAK,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,GAAE,0BAA+B,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAuBnH,+EAA+E;IAC/E,IAAI,aAAa,IAAI,iBAAiB,GAAG,SAAS,CAEjD;IAED;;;OAGG;IACH,IAAI,WAAW,IAAI,MAAM,GAAG,SAAS,CAEpC;IAED;;;OAGG;IACH,IAAI,0BAA0B,IAAI,MAAM,GAAG,SAAS,CAEnD;IAED,0CAA0C;IAC1C,IAAI,KAAK,IAAI,iBAAiB,CAE7B;IAED;;;;OAIG;IACI,WAAW,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,cAAc,CAAC,eAAe,EAAE,IAAI,EAAE,OAAO,CAAC;IAexF;;;;;;;OAOG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAKb,QAAQ;IAQtB;;;OAGG;IACH,OAAO,CAAC,OAAO;CAQhB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;IAC9D,2EAA2E;IAC3E,OAAO,CAAC,WAAW,CAAoB;IAEvC,iEAAiE;gBACrD,IAAI,EAAE,MAAM;IAOxB;;;OAGG;IACG,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYzC,yEAAyE;IACnE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAY7B;AAED,8CAA8C;AAC9C,MAAM,WAAW,mBAAoB,SAAQ,0BAA0B;IACrE,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,gDAAgD;AAChD,MAAM,WAAW,kBAAkB;IACjC,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,qBAAqB;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,KAAK,EAAE,iBAAiB,CAAC;CAC1B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,kBAAkB,CAAC,CAkD7B"}
@@ -162,6 +162,65 @@ export class ScreenStreamCapture {
162
162
  return this.assembler.push(packet);
163
163
  }
164
164
  }
165
+ /**
166
+ * The Annex-B output file, with the write stream's `'error'` event held instead
167
+ * of left to reach the process.
168
+ *
169
+ * A recording runs unattended for minutes and the stream never escapes the
170
+ * function that owns it, so a caller cannot attach a listener of its own.
171
+ * Without one here, a mistyped path or a write that fails after the fact (a full
172
+ * disk, an unplugged volume) arrives as an uncaught `'error'` event and takes
173
+ * the process down — `end(callback)` does not help, since the callback receives
174
+ * the error *and* the event is still emitted. Holding the first error and
175
+ * re-throwing it from the next `write` or `close` turns that into a rejection
176
+ * the caller can see, the guarantee {@link M4aFileWriter} already gives the
177
+ * audio track.
178
+ *
179
+ * Opening is deliberately not awaited, unlike `M4aFileWriter.create`: the
180
+ * capture is already streaming by the time the file is created, so a rejection
181
+ * before the caller holds the writer would strand it. An open failure surfaces
182
+ * from the first {@link write} instead.
183
+ */
184
+ export class AnnexBFileWriter {
185
+ stream;
186
+ /** First stream error seen, re-thrown from the next `write` or `close`. */
187
+ streamError;
188
+ /** @param path Destination file path; truncated if it exists. */
189
+ constructor(path) {
190
+ this.stream = createWriteStream(path);
191
+ this.stream.on('error', (error) => {
192
+ this.streamError ??= error;
193
+ });
194
+ }
195
+ /**
196
+ * Appends one chunk, resolving once the stream has room for more so an
197
+ * `await` per chunk applies backpressure.
198
+ */
199
+ async write(chunk) {
200
+ if (this.streamError) {
201
+ throw this.streamError;
202
+ }
203
+ if (!this.stream.write(chunk)) {
204
+ await once(this.stream, 'drain');
205
+ }
206
+ if (this.streamError) {
207
+ throw this.streamError;
208
+ }
209
+ }
210
+ /** Flushes and closes the file, re-throwing any error the stream saw. */
211
+ async close() {
212
+ // The held error is reported in preference to ending an already-failed
213
+ // stream, which answers with a generic `ERR_STREAM_DESTROYED` and buries the
214
+ // cause. That is the common path for a bad output path: the open fails
215
+ // before the first keyframe arrives, so no `write` ever ran to surface it.
216
+ if (this.streamError) {
217
+ throw this.streamError;
218
+ }
219
+ await new Promise((resolve, reject) => {
220
+ this.stream.end((error) => (error ? reject(error) : resolve()));
221
+ });
222
+ }
223
+ }
165
224
  /**
166
225
  * Records the device's screen to an Annex-B HEVC elementary stream — the
167
226
  * `.h265` layout that ffmpeg and VLC can play or remux directly:
@@ -180,7 +239,7 @@ export class ScreenStreamCapture {
180
239
  export async function recordScreenToFile(service, outputPath, options = {}) {
181
240
  const { durationMs = 5000, maxFrames = Number.POSITIVE_INFINITY, ...captureOptions } = options;
182
241
  const capture = await ScreenStreamCapture.start(service, captureOptions);
183
- const output = createWriteStream(outputPath);
242
+ const output = new AnnexBFileWriter(outputPath);
184
243
  let framesWritten = 0;
185
244
  let bytesWritten = 0;
186
245
  let sawKeyFrame = false;
@@ -200,9 +259,7 @@ export async function recordScreenToFile(service, outputPath, options = {}) {
200
259
  sawKeyFrame = true;
201
260
  }
202
261
  const chunk = toAnnexB(unit.nals);
203
- if (!output.write(chunk)) {
204
- await once(output, 'drain');
205
- }
262
+ await output.write(chunk);
206
263
  framesWritten += 1;
207
264
  bytesWritten += chunk.length;
208
265
  if (framesWritten >= maxFrames || performance.now() >= deadline) {
@@ -215,15 +272,7 @@ export async function recordScreenToFile(service, outputPath, options = {}) {
215
272
  await capture.stop().catch((error) => {
216
273
  log.debug(`Failed to stop the media stream cleanly: ${error instanceof Error ? error.message : String(error)}`);
217
274
  });
218
- await new Promise((resolve, reject) => {
219
- output.end((error) => {
220
- if (error) {
221
- reject(error);
222
- return;
223
- }
224
- resolve();
225
- });
226
- });
275
+ await output.close();
227
276
  }
228
277
  return {
229
278
  outputPath,
@@ -1 +1 @@
1
- {"version":3,"file":"screen-stream-capture.js","sourceRoot":"","sources":["../../../../../../src/services/ios/display/video/screen-stream-capture.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"screen-stream-capture.js","sourceRoot":"","sources":["../../../../../../src/services/ios/display/video/screen-stream-capture.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appium-ios-remotexpc",
3
- "version": "5.14.0",
3
+ "version": "5.14.1",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "bugs": {
@@ -1,6 +1,3 @@
1
- import {once} from 'node:events';
2
- import {createWriteStream} from 'node:fs';
3
-
4
1
  import {getLogger} from '../../../../lib/logger.js';
5
2
  import {XPCUUID} from '../../../../lib/remote-xpc/xpc-uuid.js';
6
3
  import {type AacEldFormat, aacEldDurationMs} from '../audio/aac-eld.js';
@@ -8,7 +5,7 @@ import {AudioStreamCapture, type AudioStreamStats} from '../audio/audio-stream-c
8
5
  import {M4aFileWriter} from '../audio/m4a-writer.js';
9
6
  import {type DisplayService, type StartVideoStreamOptions} from '../index.js';
10
7
  import {toAnnexB} from '../video/hevc.js';
11
- import {ScreenStreamCapture, type ScreenStreamStats} from '../video/screen-stream-capture.js';
8
+ import {AnnexBFileWriter, ScreenStreamCapture, type ScreenStreamStats} from '../video/screen-stream-capture.js';
12
9
  import {type MuxCommand, ffmpegMuxCommandBuilder} from './mux-command.js';
13
10
 
14
11
  const log = getLogger('AvCapture');
@@ -127,7 +124,7 @@ export async function recordScreenAndAudioToFiles(
127
124
  throw error;
128
125
  }
129
126
 
130
- const videoOut = createWriteStream(videoPath);
127
+ const videoOut = new AnnexBFileWriter(videoPath);
131
128
  const audioOut = await M4aFileWriter.create(audioPath);
132
129
  let framesWritten = 0;
133
130
  let videoBytes = 0;
@@ -147,9 +144,7 @@ export async function recordScreenAndAudioToFiles(
147
144
  sawKeyFrame = true;
148
145
  }
149
146
  const chunk = toAnnexB(unit.nals);
150
- if (!videoOut.write(chunk)) {
151
- await once(videoOut, 'drain');
152
- }
147
+ await videoOut.write(chunk);
153
148
  framesWritten += 1;
154
149
  videoBytes += chunk.length;
155
150
  }
@@ -180,15 +175,7 @@ export async function recordScreenAndAudioToFiles(
180
175
  });
181
176
  await audioCapture.stop().catch((): void => undefined);
182
177
  audioWritten = await audioOut.close();
183
- await new Promise<void>((resolve, reject) => {
184
- videoOut.end((error?: Error | null): void => {
185
- if (error) {
186
- reject(error);
187
- return;
188
- }
189
- resolve();
190
- });
191
- });
178
+ await videoOut.close();
192
179
  }
193
180
 
194
181
  const audioDurationMs = aacEldDurationMs(audioWritten.sampleCount);
@@ -191,6 +191,69 @@ export class ScreenStreamCapture {
191
191
  }
192
192
  }
193
193
 
194
+ /**
195
+ * The Annex-B output file, with the write stream's `'error'` event held instead
196
+ * of left to reach the process.
197
+ *
198
+ * A recording runs unattended for minutes and the stream never escapes the
199
+ * function that owns it, so a caller cannot attach a listener of its own.
200
+ * Without one here, a mistyped path or a write that fails after the fact (a full
201
+ * disk, an unplugged volume) arrives as an uncaught `'error'` event and takes
202
+ * the process down — `end(callback)` does not help, since the callback receives
203
+ * the error *and* the event is still emitted. Holding the first error and
204
+ * re-throwing it from the next `write` or `close` turns that into a rejection
205
+ * the caller can see, the guarantee {@link M4aFileWriter} already gives the
206
+ * audio track.
207
+ *
208
+ * Opening is deliberately not awaited, unlike `M4aFileWriter.create`: the
209
+ * capture is already streaming by the time the file is created, so a rejection
210
+ * before the caller holds the writer would strand it. An open failure surfaces
211
+ * from the first {@link write} instead.
212
+ */
213
+ export class AnnexBFileWriter {
214
+ private readonly stream: ReturnType<typeof createWriteStream>;
215
+ /** First stream error seen, re-thrown from the next `write` or `close`. */
216
+ private streamError: Error | undefined;
217
+
218
+ /** @param path Destination file path; truncated if it exists. */
219
+ constructor(path: string) {
220
+ this.stream = createWriteStream(path);
221
+ this.stream.on('error', (error: Error) => {
222
+ this.streamError ??= error;
223
+ });
224
+ }
225
+
226
+ /**
227
+ * Appends one chunk, resolving once the stream has room for more so an
228
+ * `await` per chunk applies backpressure.
229
+ */
230
+ async write(chunk: Buffer): Promise<void> {
231
+ if (this.streamError) {
232
+ throw this.streamError;
233
+ }
234
+ if (!this.stream.write(chunk)) {
235
+ await once(this.stream, 'drain');
236
+ }
237
+ if (this.streamError) {
238
+ throw this.streamError;
239
+ }
240
+ }
241
+
242
+ /** Flushes and closes the file, re-throwing any error the stream saw. */
243
+ async close(): Promise<void> {
244
+ // The held error is reported in preference to ending an already-failed
245
+ // stream, which answers with a generic `ERR_STREAM_DESTROYED` and buries the
246
+ // cause. That is the common path for a bad output path: the open fails
247
+ // before the first keyframe arrives, so no `write` ever ran to surface it.
248
+ if (this.streamError) {
249
+ throw this.streamError;
250
+ }
251
+ await new Promise<void>((resolve, reject) => {
252
+ this.stream.end((error?: Error | null): void => (error ? reject(error) : resolve()));
253
+ });
254
+ }
255
+ }
256
+
194
257
  /** Options for {@link recordScreenToFile}. */
195
258
  export interface RecordScreenOptions extends ScreenStreamCaptureOptions {
196
259
  /** How long to record, in milliseconds. Defaults to 5000. */
@@ -239,7 +302,7 @@ export async function recordScreenToFile(
239
302
  const {durationMs = 5000, maxFrames = Number.POSITIVE_INFINITY, ...captureOptions} = options;
240
303
 
241
304
  const capture = await ScreenStreamCapture.start(service, captureOptions);
242
- const output = createWriteStream(outputPath);
305
+ const output = new AnnexBFileWriter(outputPath);
243
306
  let framesWritten = 0;
244
307
  let bytesWritten = 0;
245
308
  let sawKeyFrame = false;
@@ -262,9 +325,7 @@ export async function recordScreenToFile(
262
325
  }
263
326
 
264
327
  const chunk = toAnnexB(unit.nals);
265
- if (!output.write(chunk)) {
266
- await once(output, 'drain');
267
- }
328
+ await output.write(chunk);
268
329
  framesWritten += 1;
269
330
  bytesWritten += chunk.length;
270
331
 
@@ -277,15 +338,7 @@ export async function recordScreenToFile(
277
338
  await capture.stop().catch((error: unknown) => {
278
339
  log.debug(`Failed to stop the media stream cleanly: ${error instanceof Error ? error.message : String(error)}`);
279
340
  });
280
- await new Promise<void>((resolve, reject) => {
281
- output.end((error?: Error | null): void => {
282
- if (error) {
283
- reject(error);
284
- return;
285
- }
286
- resolve();
287
- });
288
- });
341
+ await output.close();
289
342
  }
290
343
 
291
344
  return {