appium-ios-remotexpc 5.14.0 → 5.14.2

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,15 @@
1
+ ## [5.14.2](https://github.com/appium/appium-ios-remotexpc/compare/v5.14.1...v5.14.2) (2026-08-11)
2
+
3
+ ### Bug Fixes
4
+
5
+ * **display:** stop captures when the recording's output file cannot be created ([#290](https://github.com/appium/appium-ios-remotexpc/issues/290)) ([18ad748](https://github.com/appium/appium-ios-remotexpc/commit/18ad7480bf5a82888a7ea9a574e937ce11b5eaba))
6
+
7
+ ## [5.14.1](https://github.com/appium/appium-ios-remotexpc/compare/v5.14.0...v5.14.1) (2026-08-11)
8
+
9
+ ### Bug Fixes
10
+
11
+ * **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))
12
+
1
13
  ## [5.14.0](https://github.com/appium/appium-ios-remotexpc/compare/v5.13.6...v5.14.0) (2026-08-09)
2
14
 
3
15
  ### Features
@@ -1 +1 @@
1
- {"version":3,"file":"audio-stream-capture.d.ts","sourceRoot":"","sources":["../../../../../../src/services/ios/display/audio/audio-stream-capture.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,cAAc,EAAE,iBAAiB,EAAE,uBAAuB,EAAC,MAAM,aAAa,CAAC;AAI5F,OAAO,EAAiB,KAAK,YAAY,EAAmB,MAAM,cAAc,CAAC;AAKjF,+EAA+E;AAC/E,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qCAAqC;AACrC,MAAM,WAAW,gBAAgB;IAC/B,oEAAoE;IACpE,eAAe,EAAE,MAAM,CAAC;IACxB,yDAAyD;IACzD,WAAW,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,oDAAoD;AACpD,MAAM,WAAW,yBAA0B,SAAQ,uBAAuB;IACxE,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,kBAAkB;IAiB3B,QAAQ,CAAC,MAAM,EAAE,iBAAiB;IAhBpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IACzC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmB;IAC5C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAyB;IAEzD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAwC;IAErE,OAAO,CAAC,aAAa,CAAiF;IACtG,OAAO,CAAC,YAAY,CAAqB;IACzC,wEAAwE;IACxE,OAAO,CAAC,SAAS,CAA4B;IAC7C,kFAAkF;IAClF,OAAO,CAAC,WAAW,CAA4B;IAE/C,OAAO;IASP;;;;;;;;OAQG;WACU,KAAK,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,GAAE,yBAA8B,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAuBjH,2EAA2E;IAC3E,IAAI,MAAM,IAAI,YAAY,CAEzB;IAED,0CAA0C;IAC1C,IAAI,KAAK,IAAI,gBAAgB,CAE5B;IAED;;;;OAIG;IACI,WAAW,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,cAAc,CAAC,eAAe,EAAE,IAAI,EAAE,OAAO,CAAC;IAgCxF;;;;;;;OAOG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAKb,QAAQ;CAOvB;AAED,6CAA6C;AAC7C,MAAM,WAAW,kBAAmB,SAAQ,yBAAyB;IACnE,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,+CAA+C;AAC/C,MAAM,WAAW,iBAAiB;IAChC,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,qBAAqB;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAC;IACnB,iCAAiC;IACjC,MAAM,EAAE,YAAY,CAAC;IACrB,oDAAoD;IACpD,KAAK,EAAE,gBAAgB,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,iBAAiB,CAAC,CA8B5B"}
1
+ {"version":3,"file":"audio-stream-capture.d.ts","sourceRoot":"","sources":["../../../../../../src/services/ios/display/audio/audio-stream-capture.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,cAAc,EAAE,iBAAiB,EAAE,uBAAuB,EAAC,MAAM,aAAa,CAAC;AAI5F,OAAO,EAAiB,KAAK,YAAY,EAAmB,MAAM,cAAc,CAAC;AAKjF,+EAA+E;AAC/E,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qCAAqC;AACrC,MAAM,WAAW,gBAAgB;IAC/B,oEAAoE;IACpE,eAAe,EAAE,MAAM,CAAC;IACxB,yDAAyD;IACzD,WAAW,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,oDAAoD;AACpD,MAAM,WAAW,yBAA0B,SAAQ,uBAAuB;IACxE,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,kBAAkB;IAiB3B,QAAQ,CAAC,MAAM,EAAE,iBAAiB;IAhBpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IACzC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmB;IAC5C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAyB;IAEzD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAwC;IAErE,OAAO,CAAC,aAAa,CAAiF;IACtG,OAAO,CAAC,YAAY,CAAqB;IACzC,wEAAwE;IACxE,OAAO,CAAC,SAAS,CAA4B;IAC7C,kFAAkF;IAClF,OAAO,CAAC,WAAW,CAA4B;IAE/C,OAAO;IASP;;;;;;;;OAQG;WACU,KAAK,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,GAAE,yBAA8B,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAuBjH,2EAA2E;IAC3E,IAAI,MAAM,IAAI,YAAY,CAEzB;IAED,0CAA0C;IAC1C,IAAI,KAAK,IAAI,gBAAgB,CAE5B;IAED;;;;OAIG;IACI,WAAW,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,cAAc,CAAC,eAAe,EAAE,IAAI,EAAE,OAAO,CAAC;IAgCxF;;;;;;;OAOG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAKb,QAAQ;CAOvB;AAED,6CAA6C;AAC7C,MAAM,WAAW,kBAAmB,SAAQ,yBAAyB;IACnE,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,+CAA+C;AAC/C,MAAM,WAAW,iBAAiB;IAChC,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,qBAAqB;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAC;IACnB,iCAAiC;IACjC,MAAM,EAAE,YAAY,CAAC;IACrB,oDAAoD;IACpD,KAAK,EAAE,gBAAgB,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,iBAAiB,CAAC,CAgD5B"}
@@ -171,7 +171,22 @@ export async function recordAudioToFile(service, outputPath, options = {}) {
171
171
  const controller = new AbortController();
172
172
  const timer = setTimeout(() => controller.abort(), durationMs);
173
173
  timer.unref?.();
174
- const writer = await M4aFileWriter.create(outputPath);
174
+ let writer;
175
+ try {
176
+ writer = await M4aFileWriter.create(outputPath);
177
+ }
178
+ catch (error) {
179
+ // The capture is already streaming and never escapes this function, so a
180
+ // caller cannot stop it. Left running, the device keeps sending into a
181
+ // receiver whose queue nobody drains.
182
+ clearTimeout(timer);
183
+ // Swallowed so it cannot mask the error being thrown, but logged: a failed
184
+ // stop means the device is still streaming, which is the leak itself.
185
+ await capture.stop().catch((stopError) => {
186
+ log.debug(`Failed to stop the audio stream after the output file could not be created: ${stopError instanceof Error ? stopError.message : String(stopError)}`);
187
+ });
188
+ throw error;
189
+ }
175
190
  let written;
176
191
  try {
177
192
  for await (const unit of capture.accessUnits(controller.signal)) {
@@ -1 +1 @@
1
- {"version":3,"file":"audio-stream-capture.js","sourceRoot":"","sources":["../../../../../../src/services/ios/display/audio/audio-stream-capture.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"audio-stream-capture.js","sourceRoot":"","sources":["../../../../../../src/services/ios/display/audio/audio-stream-capture.ts"],"names":[],"mappings":"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"}
@@ -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,CA8HrC"}
@@ -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,8 +50,27 @@ export async function recordScreenAndAudioToFiles(service, options) {
52
50
  await videoCapture.stop().catch(() => undefined);
53
51
  throw error;
54
52
  }
55
- const videoOut = createWriteStream(videoPath);
56
- const audioOut = await M4aFileWriter.create(audioPath);
53
+ const videoOut = new AnnexBFileWriter(videoPath);
54
+ let audioOut;
55
+ try {
56
+ audioOut = await M4aFileWriter.create(audioPath);
57
+ }
58
+ catch (error) {
59
+ // Both captures are already streaming by now, and neither they nor the
60
+ // video writer escape this function, so a caller cannot release them. Left
61
+ // running, the device keeps encoding into a receiver whose queue nobody
62
+ // drains, and its RTCP keepalive keeps the session alive indefinitely.
63
+ // Each failure is swallowed so it cannot mask the error being thrown. The
64
+ // stop is still logged: if it fails the device is left streaming, which is
65
+ // the leak itself. One stop tears down both streams, so the second call and
66
+ // the file close are quiet.
67
+ await videoCapture.stop().catch((stopError) => {
68
+ log.debug(`Failed to stop cleanly after the audio file could not be created: ${stopError instanceof Error ? stopError.message : String(stopError)}`);
69
+ });
70
+ await audioCapture.stop().catch(() => undefined);
71
+ await videoOut.close().catch(() => undefined);
72
+ throw error;
73
+ }
57
74
  let framesWritten = 0;
58
75
  let videoBytes = 0;
59
76
  let sawKeyFrame = false;
@@ -70,9 +87,7 @@ export async function recordScreenAndAudioToFiles(service, options) {
70
87
  sawKeyFrame = true;
71
88
  }
72
89
  const chunk = toAnnexB(unit.nals);
73
- if (!videoOut.write(chunk)) {
74
- await once(videoOut, 'drain');
75
- }
90
+ await videoOut.write(chunk);
76
91
  framesWritten += 1;
77
92
  videoBytes += chunk.length;
78
93
  }
@@ -102,15 +117,7 @@ export async function recordScreenAndAudioToFiles(service, options) {
102
117
  });
103
118
  await audioCapture.stop().catch(() => undefined);
104
119
  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
- });
120
+ await videoOut.close();
114
121
  }
115
122
  const audioDurationMs = aacEldDurationMs(audioWritten.sampleCount);
116
123
  // 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":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,aAAa,CAAC;AACjC,OAAO,EAAC,iBAAiB,EAAC,MAAM,SAAS,CAAC;AAE1C,OAAO,EAAC,SAAS,EAAC,MAAM,2BAA2B,CAAC;AAEpD,OAAO,EAAC,aAAa,EAAE,4BAA4B,EAAC,MAAM,sBAAsB,CAAC;AACjF,OAAO,EAAC,gBAAgB,EAAE,cAAc,EAAC,MAAM,qBAAqB,CAAC;AACrE,OAAO,EACL,mBAAmB,GAIpB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAC,QAAQ,EAAC,MAAM,WAAW,CAAC;AAInC,MAAM,GAAG,GAAG,SAAS,CAAC,qBAAqB,CAAC,CAAC;AAQ7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,OAAO,mBAAmB;IAkBnB;IAjBM,OAAO,CAAiB;IACxB,QAAQ,CAAmB;IAC3B,SAAS,GAAG,IAAI,mBAAmB,EAAE,CAAC;IACtC,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;IACzD,wEAAwE;IAChE,SAAS,CAA4B;IAE7C;;;;OAIG;IACK,WAAW,CAA4B;IAE/C,YACE,OAAuB,EACvB,QAA0B,EACjB,MAAyB;QAAzB,WAAM,GAAN,MAAM,CAAmB;QAElC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED;;;;;;;;OAQG;IACH,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAuB,EAAE,UAAsC,EAAE;QAClF,MAAM,EAAC,YAAY,EAAE,GAAG,aAAa,EAAC,GAAG,OAAO,CAAC;QACjD,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,YAAY,EAAC,CAAC,CAAC;QACnE,IAAI,CAAC;YACH,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC;YAChH,GAAG,CAAC,KAAK,CAAC,4BAA4B,UAAU,KAAK,QAAQ,CAAC,IAAI,eAAe,QAAQ,EAAE,CAAC,CAAC;YAC7F,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,gBAAgB,CAAC,EAAC,UAAU,EAAE,YAAY,EAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAC,EAAE,aAAa,CAAC,CAAC;YAClH,MAAM,OAAO,GAAG,IAAI,mBAAmB,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;YAEnE,uEAAuE;YACvE,MAAM,QAAQ,GAAG,4BAA4B,CAAC,MAAM,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;YAC7E,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,CAAC,SAAS,GAAG,aAAa,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAC,KAAK,EAAE,OAAO,EAAC,CAAC,CAAC;YAChF,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,IAAI,CAAC,mFAAmF,CAAC,CAAC;YAChG,CAAC;YACD,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,QAAQ,CAAC,KAAK,EAAE,CAAC;YACjB,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,+EAA+E;IAC/E,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC;IACtC,CAAC;IAED;;;OAGG;IACH,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;IACpC,CAAC;IAED;;;OAGG;IACH,IAAI,0BAA0B;QAC5B,OAAO,IAAI,CAAC,SAAS,CAAC,0BAA0B,CAAC;IACnD,CAAC;IAED,0CAA0C;IAC1C,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;IAC9B,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,CAAC,WAAW,CAAC,MAAoB;QACrC,MAAM,eAAe,GAAG,GAAS,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;QACjE,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,eAAe,EAAE,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC,CAAC;QACjE,IAAI,CAAC;YACH,IAAI,KAAK,EAAE,MAAM,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC;gBAChF,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;gBACpC,IAAI,IAAI,EAAE,CAAC;oBACT,MAAM,IAAI,CAAC;gBACb,CAAC;YACH,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,IAAI;QACR,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;QACrC,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAEO,KAAK,CAAC,QAAQ;QACpB,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC;QACvB,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;QAC7B,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,SAAS,CAAC,gBAAgB,EAAE,CAAC;QAClC,MAAM,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAC3C,CAAC;IAED;;;OAGG;IACK,OAAO,CAAC,QAAgB;QAC9B,MAAM,MAAM,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,SAAS,CAAC,CAAC,2CAA2C;QAC/D,CAAC;QACD,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACjD,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC;CACF;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,OAAO,gBAAgB;IACV,MAAM,CAAuC;IAC9D,2EAA2E;IACnE,WAAW,CAAoB;IAEvC,iEAAiE;IACjE,YAAY,IAAY;QACtB,IAAI,CAAC,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAY,EAAE,EAAE;YACvC,IAAI,CAAC,WAAW,KAAK,KAAK,CAAC;QAC7B,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,KAAK,CAAC,KAAa;QACvB,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,MAAM,IAAI,CAAC,WAAW,CAAC;QACzB,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACnC,CAAC;QACD,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,MAAM,IAAI,CAAC,WAAW,CAAC;QACzB,CAAC;IACH,CAAC;IAED,yEAAyE;IACzE,KAAK,CAAC,KAAK;QACT,uEAAuE;QACvE,6EAA6E;QAC7E,uEAAuE;QACvE,2EAA2E;QAC3E,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,MAAM,IAAI,CAAC,WAAW,CAAC;QACzB,CAAC;QACD,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC1C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAoB,EAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QACvF,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AA2BD;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,OAAuB,EACvB,UAAkB,EAClB,UAA+B,EAAE;IAEjC,MAAM,EAAC,UAAU,GAAG,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC,iBAAiB,EAAE,GAAG,cAAc,EAAC,GAAG,OAAO,CAAC;IAE7F,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC,KAAK,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IACzE,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAChD,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,WAAW,GAAG,KAAK,CAAC;IAExB,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC;IAChD,MAAM,KAAK,GAAG,UAAU,CAAC,GAAS,EAAE;QAClC,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAS,EAAE,CAAC,SAAS,CAAC,CAAC;IAC9C,CAAC,EAAE,UAAU,CAAC,CAAC;IACf,6EAA6E;IAC7E,kCAAkC;IAClC,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;IAEhB,IAAI,CAAC;QACH,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;YAC/C,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;oBACrB,SAAS,CAAC,yBAAyB;gBACrC,CAAC;gBACD,WAAW,GAAG,IAAI,CAAC;YACrB,CAAC;YAED,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC1B,aAAa,IAAI,CAAC,CAAC;YACnB,YAAY,IAAI,KAAK,CAAC,MAAM,CAAC;YAE7B,IAAI,aAAa,IAAI,SAAS,IAAI,WAAW,CAAC,GAAG,EAAE,IAAI,QAAQ,EAAE,CAAC;gBAChE,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACpB,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;YAC5C,GAAG,CAAC,KAAK,CAAC,4CAA4C,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClH,CAAC,CAAC,CAAC;QACH,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IAED,OAAO;QACL,UAAU;QACV,aAAa;QACb,YAAY;QACZ,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,KAAK,EAAE,OAAO,CAAC,KAAK;KACrB,CAAC;AACJ,CAAC"}
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.2",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "bugs": {
@@ -242,7 +242,25 @@ export async function recordAudioToFile(
242
242
  const timer = setTimeout(() => controller.abort(), durationMs);
243
243
  timer.unref?.();
244
244
 
245
- const writer = await M4aFileWriter.create(outputPath);
245
+ let writer: M4aFileWriter;
246
+ try {
247
+ writer = await M4aFileWriter.create(outputPath);
248
+ } catch (error) {
249
+ // The capture is already streaming and never escapes this function, so a
250
+ // caller cannot stop it. Left running, the device keeps sending into a
251
+ // receiver whose queue nobody drains.
252
+ clearTimeout(timer);
253
+ // Swallowed so it cannot mask the error being thrown, but logged: a failed
254
+ // stop means the device is still streaming, which is the leak itself.
255
+ await capture.stop().catch((stopError: unknown) => {
256
+ log.debug(
257
+ `Failed to stop the audio stream after the output file could not be created: ${
258
+ stopError instanceof Error ? stopError.message : String(stopError)
259
+ }`,
260
+ );
261
+ });
262
+ throw error;
263
+ }
246
264
  let written;
247
265
  try {
248
266
  for await (const unit of capture.accessUnits(controller.signal)) {
@@ -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,8 +124,30 @@ export async function recordScreenAndAudioToFiles(
127
124
  throw error;
128
125
  }
129
126
 
130
- const videoOut = createWriteStream(videoPath);
131
- const audioOut = await M4aFileWriter.create(audioPath);
127
+ const videoOut = new AnnexBFileWriter(videoPath);
128
+ let audioOut: M4aFileWriter;
129
+ try {
130
+ audioOut = await M4aFileWriter.create(audioPath);
131
+ } catch (error) {
132
+ // Both captures are already streaming by now, and neither they nor the
133
+ // video writer escape this function, so a caller cannot release them. Left
134
+ // running, the device keeps encoding into a receiver whose queue nobody
135
+ // drains, and its RTCP keepalive keeps the session alive indefinitely.
136
+ // Each failure is swallowed so it cannot mask the error being thrown. The
137
+ // stop is still logged: if it fails the device is left streaming, which is
138
+ // the leak itself. One stop tears down both streams, so the second call and
139
+ // the file close are quiet.
140
+ await videoCapture.stop().catch((stopError: unknown) => {
141
+ log.debug(
142
+ `Failed to stop cleanly after the audio file could not be created: ${
143
+ stopError instanceof Error ? stopError.message : String(stopError)
144
+ }`,
145
+ );
146
+ });
147
+ await audioCapture.stop().catch((): void => undefined);
148
+ await videoOut.close().catch((): void => undefined);
149
+ throw error;
150
+ }
132
151
  let framesWritten = 0;
133
152
  let videoBytes = 0;
134
153
  let sawKeyFrame = false;
@@ -147,9 +166,7 @@ export async function recordScreenAndAudioToFiles(
147
166
  sawKeyFrame = true;
148
167
  }
149
168
  const chunk = toAnnexB(unit.nals);
150
- if (!videoOut.write(chunk)) {
151
- await once(videoOut, 'drain');
152
- }
169
+ await videoOut.write(chunk);
153
170
  framesWritten += 1;
154
171
  videoBytes += chunk.length;
155
172
  }
@@ -180,15 +197,7 @@ export async function recordScreenAndAudioToFiles(
180
197
  });
181
198
  await audioCapture.stop().catch((): void => undefined);
182
199
  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
- });
200
+ await videoOut.close();
192
201
  }
193
202
 
194
203
  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 {