@midscene/android 1.12.1-beta-20260826131413.0 → 1.12.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/dist/es/cli.mjs CHANGED
@@ -32,10 +32,11 @@ var __webpack_modules__ = {
32
32
  ScrcpyScreenshotManager: ()=>ScrcpyScreenshotManager,
33
33
  ov: ()=>DEFAULT_SCRCPY_CONFIG
34
34
  });
35
- var node_module__rspack_import_0 = __webpack_require__("node:module");
36
- var node_path__rspack_import_1 = __webpack_require__("node:path");
37
- var _midscene_shared_logger__rspack_import_2 = __webpack_require__("@midscene/shared/logger");
38
- var _resource_path__rspack_import_3 = __webpack_require__("./src/resource-path.ts");
35
+ var node_fs__rspack_import_0 = __webpack_require__("node:fs");
36
+ var node_module__rspack_import_1 = __webpack_require__("node:module");
37
+ var node_path__rspack_import_2 = __webpack_require__("node:path");
38
+ var _midscene_shared_logger__rspack_import_3 = __webpack_require__("@midscene/shared/logger");
39
+ var _resource_path__rspack_import_4 = __webpack_require__("./src/resource-path.ts");
39
40
  function _define_property(obj, key, value) {
40
41
  if (key in obj) Object.defineProperty(obj, key, {
41
42
  value: value,
@@ -46,8 +47,8 @@ var __webpack_modules__ = {
46
47
  else obj[key] = value;
47
48
  return obj;
48
49
  }
49
- const debugScrcpy = (0, _midscene_shared_logger__rspack_import_2.getDebug)('android:scrcpy');
50
- const warnScrcpy = (0, _midscene_shared_logger__rspack_import_2.getDebug)('android:scrcpy', {
50
+ const debugScrcpy = (0, _midscene_shared_logger__rspack_import_3.getDebug)('android:scrcpy');
51
+ const warnScrcpy = (0, _midscene_shared_logger__rspack_import_3.getDebug)('android:scrcpy', {
51
52
  console: true
52
53
  });
53
54
  const NAL_TYPE_IDR = 5;
@@ -80,9 +81,6 @@ var __webpack_modules__ = {
80
81
  idleTimeoutMs: DEFAULT_IDLE_TIMEOUT_MS,
81
82
  videoBitRate: DEFAULT_VIDEO_BIT_RATE
82
83
  };
83
- const missingScrcpyServerPusher = async ()=>{
84
- throw new Error('Scrcpy server pusher is not configured');
85
- };
86
84
  const SCRCPY_FRESH_FRAME_UNAVAILABLE_ERROR_CODE = 'ERR_SCRCPY_FRESH_FRAME_UNAVAILABLE';
87
85
  class ScrcpyFreshFrameUnavailableError extends Error {
88
86
  constructor(message, options){
@@ -149,9 +147,10 @@ var __webpack_modules__ = {
149
147
  try {
150
148
  debugScrcpy('Starting scrcpy connection...');
151
149
  const { AdbScrcpyClient } = await import("@yume-chan/adb-scrcpy");
150
+ const { ReadableStream } = await import("@yume-chan/stream-extra");
152
151
  const { DefaultServerPath } = await import("@yume-chan/scrcpy");
153
152
  const serverBinPath = this.resolveServerBinPath();
154
- await this.pushServerBinary(serverBinPath, DefaultServerPath);
153
+ await AdbScrcpyClient.pushServer(this.adb, ReadableStream.from((0, node_fs__rspack_import_0.createReadStream)(serverBinPath)));
155
154
  const scrcpyOptions = await this.createScrcpyOptions();
156
155
  await this.ensureFrameClockCalibration();
157
156
  this.scrcpyClient = await AdbScrcpyClient.start(this.adb, DefaultServerPath, scrcpyOptions);
@@ -182,9 +181,6 @@ var __webpack_modules__ = {
182
181
  throw this.createConnectionError(error, serverOutput);
183
182
  }
184
183
  }
185
- async pushServerBinary(serverBinPath, remoteServerPath) {
186
- await this.pushServer(serverBinPath, remoteServerPath);
187
- }
188
184
  async createScrcpyOptions() {
189
185
  const [{ AdbScrcpyOptions3_3_3 }, { ScrcpyInstanceId }] = await Promise.all([
190
186
  import("@yume-chan/adb-scrcpy"),
@@ -238,12 +234,12 @@ var __webpack_modules__ = {
238
234
  return output.filter((line)=>'string' == typeof line);
239
235
  }
240
236
  resolveServerBinPath() {
241
- const androidPkgJson = (0, node_module__rspack_import_0.createRequire)(import.meta.url).resolve('@midscene/android/package.json');
242
- return (0, _resource_path__rspack_import_3.J)(node_path__rspack_import_1["default"].join(node_path__rspack_import_1["default"].dirname(androidPkgJson), 'bin', 'scrcpy-server'));
237
+ const androidPkgJson = (0, node_module__rspack_import_1.createRequire)(import.meta.url).resolve('@midscene/android/package.json');
238
+ return (0, _resource_path__rspack_import_4.J)(node_path__rspack_import_2["default"].join(node_path__rspack_import_2["default"].dirname(androidPkgJson), 'bin', 'scrcpy-server'));
243
239
  }
244
240
  getFfmpegPath() {
245
241
  try {
246
- const dynamicRequire = (0, node_module__rspack_import_0.createRequire)(import.meta.url);
242
+ const dynamicRequire = (0, node_module__rspack_import_1.createRequire)(import.meta.url);
247
243
  const ffmpegInstaller = dynamicRequire('@ffmpeg-installer/ffmpeg');
248
244
  debugScrcpy(`Using ffmpeg from npm package: ${ffmpegInstaller.path}`);
249
245
  return ffmpegInstaller.path;
@@ -782,63 +778,36 @@ var __webpack_modules__ = {
782
778
  isConnected() {
783
779
  return this.isInitialized && null !== this.scrcpyClient;
784
780
  }
785
- constructor(adb, options = {}, pushServer = missingScrcpyServerPusher){
786
- _define_property(this, "pushServer", void 0);
781
+ constructor(adb, options = {}){
787
782
  _define_property(this, "adb", void 0);
788
- _define_property(this, "scrcpyClient", void 0);
789
- _define_property(this, "videoStream", void 0);
790
- _define_property(this, "spsHeader", void 0);
791
- _define_property(this, "idleTimer", void 0);
792
- _define_property(this, "connectionPromise", void 0);
793
- _define_property(this, "disposed", void 0);
794
- _define_property(this, "isInitialized", void 0);
783
+ _define_property(this, "scrcpyClient", null);
784
+ _define_property(this, "videoStream", null);
785
+ _define_property(this, "spsHeader", null);
786
+ _define_property(this, "idleTimer", null);
787
+ _define_property(this, "connectionPromise", null);
788
+ _define_property(this, "disposed", false);
789
+ _define_property(this, "isInitialized", false);
795
790
  _define_property(this, "options", void 0);
796
- _define_property(this, "ffmpegAvailable", void 0);
797
- _define_property(this, "keyframeResolvers", void 0);
798
- _define_property(this, "keyframeListeners", void 0);
799
- _define_property(this, "lastRawKeyframe", void 0);
800
- _define_property(this, "lastRawKeyframeAt", void 0);
791
+ _define_property(this, "ffmpegAvailable", null);
792
+ _define_property(this, "keyframeResolvers", []);
793
+ _define_property(this, "keyframeListeners", new Set());
794
+ _define_property(this, "lastRawKeyframe", null);
795
+ _define_property(this, "lastRawKeyframeAt", 0);
801
796
  _define_property(this, "lastRawKeyframePtsUs", void 0);
802
797
  _define_property(this, "lastRawKeyframeEstimatedAgeMs", void 0);
803
- _define_property(this, "videoResolution", void 0);
804
- _define_property(this, "streamReader", void 0);
805
- _define_property(this, "frameFreshnessBarrierPtsUs", void 0);
806
- _define_property(this, "frameFreshnessBarrierReason", void 0);
807
- _define_property(this, "streamStartupWindow", void 0);
808
- _define_property(this, "frameFreshnessBarrierPending", void 0);
809
- _define_property(this, "frameFreshnessBarrierGeneration", void 0);
810
- _define_property(this, "deviceClockCalibration", void 0);
811
- _define_property(this, "deviceClockCalibrationPromise", void 0);
812
- _define_property(this, "lastFramePtsUs", void 0);
813
- _define_property(this, "frameFreshnessError", void 0);
814
- _define_property(this, "lastFrameFreshnessWarningAt", void 0);
815
- _define_property(this, "disposePromise", void 0);
816
- this.pushServer = pushServer;
817
- this.scrcpyClient = null;
818
- this.videoStream = null;
819
- this.spsHeader = null;
820
- this.idleTimer = null;
821
- this.connectionPromise = null;
822
- this.disposed = false;
823
- this.isInitialized = false;
824
- this.ffmpegAvailable = null;
825
- this.keyframeResolvers = [];
826
- this.keyframeListeners = new Set();
827
- this.lastRawKeyframe = null;
828
- this.lastRawKeyframeAt = 0;
829
- this.videoResolution = null;
830
- this.streamReader = null;
831
- this.frameFreshnessBarrierPtsUs = null;
832
- this.frameFreshnessBarrierReason = null;
833
- this.streamStartupWindow = null;
834
- this.frameFreshnessBarrierPending = false;
835
- this.frameFreshnessBarrierGeneration = 0;
836
- this.deviceClockCalibration = null;
837
- this.deviceClockCalibrationPromise = null;
838
- this.lastFramePtsUs = null;
839
- this.frameFreshnessError = null;
840
- this.lastFrameFreshnessWarningAt = 0;
841
- this.disposePromise = null;
798
+ _define_property(this, "videoResolution", null);
799
+ _define_property(this, "streamReader", null);
800
+ _define_property(this, "frameFreshnessBarrierPtsUs", null);
801
+ _define_property(this, "frameFreshnessBarrierReason", null);
802
+ _define_property(this, "streamStartupWindow", null);
803
+ _define_property(this, "frameFreshnessBarrierPending", false);
804
+ _define_property(this, "frameFreshnessBarrierGeneration", 0);
805
+ _define_property(this, "deviceClockCalibration", null);
806
+ _define_property(this, "deviceClockCalibrationPromise", null);
807
+ _define_property(this, "lastFramePtsUs", null);
808
+ _define_property(this, "frameFreshnessError", null);
809
+ _define_property(this, "lastFrameFreshnessWarningAt", 0);
810
+ _define_property(this, "disposePromise", null);
842
811
  this.adb = adb;
843
812
  const requestedBitRate = options.videoBitRate ?? DEFAULT_VIDEO_BIT_RATE;
844
813
  const clampedBitRate = Math.min(requestedBitRate, MAX_VIDEO_BIT_RATE);
@@ -1074,7 +1043,7 @@ function formatScrcpyFreshFrameFailure(error) {
1074
1043
  const bitRateDescription = Number.isFinite(videoBitRate) ? ` Current videoBitRate: ${videoBitRate} bps (${videoBitRate / 1000000} Mbps).` : '';
1075
1044
  return `No usable scrcpy frame crossed the active freshness target within ${timeoutMs}ms. This can happen when a static screen emits no new encoded frame, or when the video stream or transport is interrupted. This timeout does not by itself identify bandwidth or the configured video bitrate as the cause.${bitRateDescription}`;
1076
1045
  }
1077
- const DEFAULT_ADB_SERVER_CONNECTION = {
1046
+ const DEFAULT_ADB_SERVER_ENDPOINT = {
1078
1047
  host: '127.0.0.1',
1079
1048
  port: 5037
1080
1049
  };
@@ -1142,21 +1111,17 @@ class ScrcpyDeviceAdapter {
1142
1111
  const { Adb, AdbServerClient } = await import("@yume-chan/adb");
1143
1112
  const { AdbServerNodeTcpConnector } = await import("@yume-chan/adb-server-node-tcp");
1144
1113
  const { ScrcpyScreenshotManager: ScrcpyManager } = await Promise.resolve().then(__webpack_require__.bind(__webpack_require__, "./src/scrcpy-manager.ts"));
1145
- const adbServerConnection = await this.resolveAdbServerEndpoint();
1146
- const adbClient = new AdbServerClient(new AdbServerNodeTcpConnector({
1147
- host: adbServerConnection.host,
1148
- port: adbServerConnection.port
1149
- }));
1114
+ const adbServerEndpoint = await this.resolveAdbServerEndpoint();
1115
+ const adbClient = new AdbServerClient(new AdbServerNodeTcpConnector(adbServerEndpoint));
1150
1116
  adb = new Adb(await adbClient.createTransport({
1151
1117
  serial: this.deviceId
1152
1118
  }));
1153
1119
  const config = this.resolveConfig();
1154
- const serverPusher = adbServerConnection.pushServer ?? this.createDefaultServerPusher(adbServerConnection);
1155
1120
  manager = new ScrcpyManager(adb, {
1156
1121
  maxSize: config.maxSize,
1157
1122
  videoBitRate: config.videoBitRate,
1158
1123
  idleTimeoutMs: config.idleTimeoutMs
1159
- }, serverPusher);
1124
+ });
1160
1125
  await manager.validateEnvironment();
1161
1126
  if (generation !== this.lifecycleGeneration) throw new Error('Scrcpy manager initialization was superseded by device cleanup');
1162
1127
  this.manager = manager;
@@ -1180,17 +1145,6 @@ class ScrcpyDeviceAdapter {
1180
1145
  if (this.managerPromise === managerPromise) this.managerPromise = null;
1181
1146
  }
1182
1147
  }
1183
- createDefaultServerPusher(endpoint) {
1184
- let fileTransferAdb;
1185
- return async (localPath, remotePath)=>{
1186
- fileTransferAdb ??= new ADB({
1187
- udid: this.deviceId,
1188
- remoteAdbHost: endpoint.host,
1189
- remoteAdbPort: endpoint.port
1190
- });
1191
- await fileTransferAdb.push(localPath, remotePath);
1192
- };
1193
- }
1194
1148
  async ensureConnectedManager(deviceInfo) {
1195
1149
  const manager = await this.ensureManager(deviceInfo);
1196
1150
  const wasConnected = manager.isConnected();
@@ -1357,7 +1311,7 @@ class ScrcpyDeviceAdapter {
1357
1311
  this.resolvedConfig = null;
1358
1312
  this.clearFailure();
1359
1313
  }
1360
- constructor(deviceId, scrcpyConfig, resolveAdbServerEndpoint = ()=>DEFAULT_ADB_SERVER_CONNECTION){
1314
+ constructor(deviceId, scrcpyConfig, resolveAdbServerEndpoint = ()=>DEFAULT_ADB_SERVER_ENDPOINT){
1361
1315
  _define_property(this, "deviceId", void 0);
1362
1316
  _define_property(this, "scrcpyConfig", void 0);
1363
1317
  _define_property(this, "resolveAdbServerEndpoint", void 0);
@@ -1877,10 +1831,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1877
1831
  const adb = await this.getAdb();
1878
1832
  return {
1879
1833
  host: adb.adbHost ?? '127.0.0.1',
1880
- port: adb.adbPort ?? 5037,
1881
- pushServer: async (localPath, remotePath)=>{
1882
- await adb.push(localPath, remotePath);
1883
- }
1834
+ port: adb.adbPort ?? 5037
1884
1835
  };
1885
1836
  });
1886
1837
  return this.scrcpyAdapter;
@@ -3254,7 +3205,7 @@ class AndroidMidsceneTools extends BaseMidsceneTools {
3254
3205
  const tools = new AndroidMidsceneTools();
3255
3206
  runToolsCLI(tools, 'midscene-android', {
3256
3207
  stripPrefix: 'android_',
3257
- version: "1.12.1-beta-20260826131413.0",
3208
+ version: "1.12.1",
3258
3209
  extraCommands: createReportCliCommands()
3259
3210
  }).catch((e)=>{
3260
3211
  process.exit(reportCLIError(e));
package/dist/es/index.mjs CHANGED
@@ -31,10 +31,11 @@ var __webpack_modules__ = {
31
31
  ScrcpyScreenshotManager: ()=>ScrcpyScreenshotManager,
32
32
  ov: ()=>DEFAULT_SCRCPY_CONFIG
33
33
  });
34
- var node_module__rspack_import_0 = __webpack_require__("node:module");
35
- var node_path__rspack_import_1 = __webpack_require__("node:path");
36
- var _midscene_shared_logger__rspack_import_2 = __webpack_require__("@midscene/shared/logger");
37
- var _resource_path__rspack_import_3 = __webpack_require__("./src/resource-path.ts");
34
+ var node_fs__rspack_import_0 = __webpack_require__("node:fs");
35
+ var node_module__rspack_import_1 = __webpack_require__("node:module");
36
+ var node_path__rspack_import_2 = __webpack_require__("node:path");
37
+ var _midscene_shared_logger__rspack_import_3 = __webpack_require__("@midscene/shared/logger");
38
+ var _resource_path__rspack_import_4 = __webpack_require__("./src/resource-path.ts");
38
39
  function _define_property(obj, key, value) {
39
40
  if (key in obj) Object.defineProperty(obj, key, {
40
41
  value: value,
@@ -45,8 +46,8 @@ var __webpack_modules__ = {
45
46
  else obj[key] = value;
46
47
  return obj;
47
48
  }
48
- const debugScrcpy = (0, _midscene_shared_logger__rspack_import_2.getDebug)('android:scrcpy');
49
- const warnScrcpy = (0, _midscene_shared_logger__rspack_import_2.getDebug)('android:scrcpy', {
49
+ const debugScrcpy = (0, _midscene_shared_logger__rspack_import_3.getDebug)('android:scrcpy');
50
+ const warnScrcpy = (0, _midscene_shared_logger__rspack_import_3.getDebug)('android:scrcpy', {
50
51
  console: true
51
52
  });
52
53
  const NAL_TYPE_IDR = 5;
@@ -79,9 +80,6 @@ var __webpack_modules__ = {
79
80
  idleTimeoutMs: DEFAULT_IDLE_TIMEOUT_MS,
80
81
  videoBitRate: DEFAULT_VIDEO_BIT_RATE
81
82
  };
82
- const missingScrcpyServerPusher = async ()=>{
83
- throw new Error('Scrcpy server pusher is not configured');
84
- };
85
83
  const SCRCPY_FRESH_FRAME_UNAVAILABLE_ERROR_CODE = 'ERR_SCRCPY_FRESH_FRAME_UNAVAILABLE';
86
84
  class ScrcpyFreshFrameUnavailableError extends Error {
87
85
  constructor(message, options){
@@ -148,9 +146,10 @@ var __webpack_modules__ = {
148
146
  try {
149
147
  debugScrcpy('Starting scrcpy connection...');
150
148
  const { AdbScrcpyClient } = await import("@yume-chan/adb-scrcpy");
149
+ const { ReadableStream } = await import("@yume-chan/stream-extra");
151
150
  const { DefaultServerPath } = await import("@yume-chan/scrcpy");
152
151
  const serverBinPath = this.resolveServerBinPath();
153
- await this.pushServerBinary(serverBinPath, DefaultServerPath);
152
+ await AdbScrcpyClient.pushServer(this.adb, ReadableStream.from((0, node_fs__rspack_import_0.createReadStream)(serverBinPath)));
154
153
  const scrcpyOptions = await this.createScrcpyOptions();
155
154
  await this.ensureFrameClockCalibration();
156
155
  this.scrcpyClient = await AdbScrcpyClient.start(this.adb, DefaultServerPath, scrcpyOptions);
@@ -181,9 +180,6 @@ var __webpack_modules__ = {
181
180
  throw this.createConnectionError(error, serverOutput);
182
181
  }
183
182
  }
184
- async pushServerBinary(serverBinPath, remoteServerPath) {
185
- await this.pushServer(serverBinPath, remoteServerPath);
186
- }
187
183
  async createScrcpyOptions() {
188
184
  const [{ AdbScrcpyOptions3_3_3 }, { ScrcpyInstanceId }] = await Promise.all([
189
185
  import("@yume-chan/adb-scrcpy"),
@@ -237,12 +233,12 @@ var __webpack_modules__ = {
237
233
  return output.filter((line)=>'string' == typeof line);
238
234
  }
239
235
  resolveServerBinPath() {
240
- const androidPkgJson = (0, node_module__rspack_import_0.createRequire)(import.meta.url).resolve('@midscene/android/package.json');
241
- return (0, _resource_path__rspack_import_3.J)(node_path__rspack_import_1["default"].join(node_path__rspack_import_1["default"].dirname(androidPkgJson), 'bin', 'scrcpy-server'));
236
+ const androidPkgJson = (0, node_module__rspack_import_1.createRequire)(import.meta.url).resolve('@midscene/android/package.json');
237
+ return (0, _resource_path__rspack_import_4.J)(node_path__rspack_import_2["default"].join(node_path__rspack_import_2["default"].dirname(androidPkgJson), 'bin', 'scrcpy-server'));
242
238
  }
243
239
  getFfmpegPath() {
244
240
  try {
245
- const dynamicRequire = (0, node_module__rspack_import_0.createRequire)(import.meta.url);
241
+ const dynamicRequire = (0, node_module__rspack_import_1.createRequire)(import.meta.url);
246
242
  const ffmpegInstaller = dynamicRequire('@ffmpeg-installer/ffmpeg');
247
243
  debugScrcpy(`Using ffmpeg from npm package: ${ffmpegInstaller.path}`);
248
244
  return ffmpegInstaller.path;
@@ -781,63 +777,36 @@ var __webpack_modules__ = {
781
777
  isConnected() {
782
778
  return this.isInitialized && null !== this.scrcpyClient;
783
779
  }
784
- constructor(adb, options = {}, pushServer = missingScrcpyServerPusher){
785
- _define_property(this, "pushServer", void 0);
780
+ constructor(adb, options = {}){
786
781
  _define_property(this, "adb", void 0);
787
- _define_property(this, "scrcpyClient", void 0);
788
- _define_property(this, "videoStream", void 0);
789
- _define_property(this, "spsHeader", void 0);
790
- _define_property(this, "idleTimer", void 0);
791
- _define_property(this, "connectionPromise", void 0);
792
- _define_property(this, "disposed", void 0);
793
- _define_property(this, "isInitialized", void 0);
782
+ _define_property(this, "scrcpyClient", null);
783
+ _define_property(this, "videoStream", null);
784
+ _define_property(this, "spsHeader", null);
785
+ _define_property(this, "idleTimer", null);
786
+ _define_property(this, "connectionPromise", null);
787
+ _define_property(this, "disposed", false);
788
+ _define_property(this, "isInitialized", false);
794
789
  _define_property(this, "options", void 0);
795
- _define_property(this, "ffmpegAvailable", void 0);
796
- _define_property(this, "keyframeResolvers", void 0);
797
- _define_property(this, "keyframeListeners", void 0);
798
- _define_property(this, "lastRawKeyframe", void 0);
799
- _define_property(this, "lastRawKeyframeAt", void 0);
790
+ _define_property(this, "ffmpegAvailable", null);
791
+ _define_property(this, "keyframeResolvers", []);
792
+ _define_property(this, "keyframeListeners", new Set());
793
+ _define_property(this, "lastRawKeyframe", null);
794
+ _define_property(this, "lastRawKeyframeAt", 0);
800
795
  _define_property(this, "lastRawKeyframePtsUs", void 0);
801
796
  _define_property(this, "lastRawKeyframeEstimatedAgeMs", void 0);
802
- _define_property(this, "videoResolution", void 0);
803
- _define_property(this, "streamReader", void 0);
804
- _define_property(this, "frameFreshnessBarrierPtsUs", void 0);
805
- _define_property(this, "frameFreshnessBarrierReason", void 0);
806
- _define_property(this, "streamStartupWindow", void 0);
807
- _define_property(this, "frameFreshnessBarrierPending", void 0);
808
- _define_property(this, "frameFreshnessBarrierGeneration", void 0);
809
- _define_property(this, "deviceClockCalibration", void 0);
810
- _define_property(this, "deviceClockCalibrationPromise", void 0);
811
- _define_property(this, "lastFramePtsUs", void 0);
812
- _define_property(this, "frameFreshnessError", void 0);
813
- _define_property(this, "lastFrameFreshnessWarningAt", void 0);
814
- _define_property(this, "disposePromise", void 0);
815
- this.pushServer = pushServer;
816
- this.scrcpyClient = null;
817
- this.videoStream = null;
818
- this.spsHeader = null;
819
- this.idleTimer = null;
820
- this.connectionPromise = null;
821
- this.disposed = false;
822
- this.isInitialized = false;
823
- this.ffmpegAvailable = null;
824
- this.keyframeResolvers = [];
825
- this.keyframeListeners = new Set();
826
- this.lastRawKeyframe = null;
827
- this.lastRawKeyframeAt = 0;
828
- this.videoResolution = null;
829
- this.streamReader = null;
830
- this.frameFreshnessBarrierPtsUs = null;
831
- this.frameFreshnessBarrierReason = null;
832
- this.streamStartupWindow = null;
833
- this.frameFreshnessBarrierPending = false;
834
- this.frameFreshnessBarrierGeneration = 0;
835
- this.deviceClockCalibration = null;
836
- this.deviceClockCalibrationPromise = null;
837
- this.lastFramePtsUs = null;
838
- this.frameFreshnessError = null;
839
- this.lastFrameFreshnessWarningAt = 0;
840
- this.disposePromise = null;
797
+ _define_property(this, "videoResolution", null);
798
+ _define_property(this, "streamReader", null);
799
+ _define_property(this, "frameFreshnessBarrierPtsUs", null);
800
+ _define_property(this, "frameFreshnessBarrierReason", null);
801
+ _define_property(this, "streamStartupWindow", null);
802
+ _define_property(this, "frameFreshnessBarrierPending", false);
803
+ _define_property(this, "frameFreshnessBarrierGeneration", 0);
804
+ _define_property(this, "deviceClockCalibration", null);
805
+ _define_property(this, "deviceClockCalibrationPromise", null);
806
+ _define_property(this, "lastFramePtsUs", null);
807
+ _define_property(this, "frameFreshnessError", null);
808
+ _define_property(this, "lastFrameFreshnessWarningAt", 0);
809
+ _define_property(this, "disposePromise", null);
841
810
  this.adb = adb;
842
811
  const requestedBitRate = options.videoBitRate ?? DEFAULT_VIDEO_BIT_RATE;
843
812
  const clampedBitRate = Math.min(requestedBitRate, MAX_VIDEO_BIT_RATE);
@@ -977,7 +946,7 @@ function formatScrcpyFreshFrameFailure(error) {
977
946
  const bitRateDescription = Number.isFinite(videoBitRate) ? ` Current videoBitRate: ${videoBitRate} bps (${videoBitRate / 1000000} Mbps).` : '';
978
947
  return `No usable scrcpy frame crossed the active freshness target within ${timeoutMs}ms. This can happen when a static screen emits no new encoded frame, or when the video stream or transport is interrupted. This timeout does not by itself identify bandwidth or the configured video bitrate as the cause.${bitRateDescription}`;
979
948
  }
980
- const DEFAULT_ADB_SERVER_CONNECTION = {
949
+ const DEFAULT_ADB_SERVER_ENDPOINT = {
981
950
  host: '127.0.0.1',
982
951
  port: 5037
983
952
  };
@@ -1045,21 +1014,17 @@ class ScrcpyDeviceAdapter {
1045
1014
  const { Adb, AdbServerClient } = await import("@yume-chan/adb");
1046
1015
  const { AdbServerNodeTcpConnector } = await import("@yume-chan/adb-server-node-tcp");
1047
1016
  const { ScrcpyScreenshotManager: ScrcpyManager } = await Promise.resolve().then(__webpack_require__.bind(__webpack_require__, "./src/scrcpy-manager.ts"));
1048
- const adbServerConnection = await this.resolveAdbServerEndpoint();
1049
- const adbClient = new AdbServerClient(new AdbServerNodeTcpConnector({
1050
- host: adbServerConnection.host,
1051
- port: adbServerConnection.port
1052
- }));
1017
+ const adbServerEndpoint = await this.resolveAdbServerEndpoint();
1018
+ const adbClient = new AdbServerClient(new AdbServerNodeTcpConnector(adbServerEndpoint));
1053
1019
  adb = new Adb(await adbClient.createTransport({
1054
1020
  serial: this.deviceId
1055
1021
  }));
1056
1022
  const config = this.resolveConfig();
1057
- const serverPusher = adbServerConnection.pushServer ?? this.createDefaultServerPusher(adbServerConnection);
1058
1023
  manager = new ScrcpyManager(adb, {
1059
1024
  maxSize: config.maxSize,
1060
1025
  videoBitRate: config.videoBitRate,
1061
1026
  idleTimeoutMs: config.idleTimeoutMs
1062
- }, serverPusher);
1027
+ });
1063
1028
  await manager.validateEnvironment();
1064
1029
  if (generation !== this.lifecycleGeneration) throw new Error('Scrcpy manager initialization was superseded by device cleanup');
1065
1030
  this.manager = manager;
@@ -1083,17 +1048,6 @@ class ScrcpyDeviceAdapter {
1083
1048
  if (this.managerPromise === managerPromise) this.managerPromise = null;
1084
1049
  }
1085
1050
  }
1086
- createDefaultServerPusher(endpoint) {
1087
- let fileTransferAdb;
1088
- return async (localPath, remotePath)=>{
1089
- fileTransferAdb ??= new ADB({
1090
- udid: this.deviceId,
1091
- remoteAdbHost: endpoint.host,
1092
- remoteAdbPort: endpoint.port
1093
- });
1094
- await fileTransferAdb.push(localPath, remotePath);
1095
- };
1096
- }
1097
1051
  async ensureConnectedManager(deviceInfo) {
1098
1052
  const manager = await this.ensureManager(deviceInfo);
1099
1053
  const wasConnected = manager.isConnected();
@@ -1260,7 +1214,7 @@ class ScrcpyDeviceAdapter {
1260
1214
  this.resolvedConfig = null;
1261
1215
  this.clearFailure();
1262
1216
  }
1263
- constructor(deviceId, scrcpyConfig, resolveAdbServerEndpoint = ()=>DEFAULT_ADB_SERVER_CONNECTION){
1217
+ constructor(deviceId, scrcpyConfig, resolveAdbServerEndpoint = ()=>DEFAULT_ADB_SERVER_ENDPOINT){
1264
1218
  _define_property(this, "deviceId", void 0);
1265
1219
  _define_property(this, "scrcpyConfig", void 0);
1266
1220
  _define_property(this, "resolveAdbServerEndpoint", void 0);
@@ -1780,10 +1734,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1780
1734
  const adb = await this.getAdb();
1781
1735
  return {
1782
1736
  host: adb.adbHost ?? '127.0.0.1',
1783
- port: adb.adbPort ?? 5037,
1784
- pushServer: async (localPath, remotePath)=>{
1785
- await adb.push(localPath, remotePath);
1786
- }
1737
+ port: adb.adbPort ?? 5037
1787
1738
  };
1788
1739
  });
1789
1740
  return this.scrcpyAdapter;
package/dist/lib/cli.js CHANGED
@@ -19,11 +19,12 @@ var __webpack_modules__ = {
19
19
  ScrcpyScreenshotManager: ()=>ScrcpyScreenshotManager,
20
20
  ov: ()=>DEFAULT_SCRCPY_CONFIG
21
21
  });
22
- var node_module__rspack_import_0 = __webpack_require__("node:module");
23
- var node_path__rspack_import_1 = __webpack_require__("node:path");
24
- var node_path__rspack_import_1_default = /*#__PURE__*/ __webpack_require__.n(node_path__rspack_import_1);
25
- var _midscene_shared_logger__rspack_import_2 = __webpack_require__("@midscene/shared/logger");
26
- var _resource_path__rspack_import_3 = __webpack_require__("./src/resource-path.ts");
22
+ var node_fs__rspack_import_0 = __webpack_require__("node:fs");
23
+ var node_module__rspack_import_1 = __webpack_require__("node:module");
24
+ var node_path__rspack_import_2 = __webpack_require__("node:path");
25
+ var node_path__rspack_import_2_default = /*#__PURE__*/ __webpack_require__.n(node_path__rspack_import_2);
26
+ var _midscene_shared_logger__rspack_import_3 = __webpack_require__("@midscene/shared/logger");
27
+ var _resource_path__rspack_import_4 = __webpack_require__("./src/resource-path.ts");
27
28
  function _define_property(obj, key, value) {
28
29
  if (key in obj) Object.defineProperty(obj, key, {
29
30
  value: value,
@@ -34,8 +35,8 @@ var __webpack_modules__ = {
34
35
  else obj[key] = value;
35
36
  return obj;
36
37
  }
37
- const debugScrcpy = (0, _midscene_shared_logger__rspack_import_2.getDebug)('android:scrcpy');
38
- const warnScrcpy = (0, _midscene_shared_logger__rspack_import_2.getDebug)('android:scrcpy', {
38
+ const debugScrcpy = (0, _midscene_shared_logger__rspack_import_3.getDebug)('android:scrcpy');
39
+ const warnScrcpy = (0, _midscene_shared_logger__rspack_import_3.getDebug)('android:scrcpy', {
39
40
  console: true
40
41
  });
41
42
  const NAL_TYPE_IDR = 5;
@@ -68,9 +69,6 @@ var __webpack_modules__ = {
68
69
  idleTimeoutMs: DEFAULT_IDLE_TIMEOUT_MS,
69
70
  videoBitRate: DEFAULT_VIDEO_BIT_RATE
70
71
  };
71
- const missingScrcpyServerPusher = async ()=>{
72
- throw new Error('Scrcpy server pusher is not configured');
73
- };
74
72
  const SCRCPY_FRESH_FRAME_UNAVAILABLE_ERROR_CODE = 'ERR_SCRCPY_FRESH_FRAME_UNAVAILABLE';
75
73
  class ScrcpyFreshFrameUnavailableError extends Error {
76
74
  constructor(message, options){
@@ -137,9 +135,10 @@ var __webpack_modules__ = {
137
135
  try {
138
136
  debugScrcpy('Starting scrcpy connection...');
139
137
  const { AdbScrcpyClient } = await import("@yume-chan/adb-scrcpy");
138
+ const { ReadableStream } = await import("@yume-chan/stream-extra");
140
139
  const { DefaultServerPath } = await import("@yume-chan/scrcpy");
141
140
  const serverBinPath = this.resolveServerBinPath();
142
- await this.pushServerBinary(serverBinPath, DefaultServerPath);
141
+ await AdbScrcpyClient.pushServer(this.adb, ReadableStream.from((0, node_fs__rspack_import_0.createReadStream)(serverBinPath)));
143
142
  const scrcpyOptions = await this.createScrcpyOptions();
144
143
  await this.ensureFrameClockCalibration();
145
144
  this.scrcpyClient = await AdbScrcpyClient.start(this.adb, DefaultServerPath, scrcpyOptions);
@@ -170,9 +169,6 @@ var __webpack_modules__ = {
170
169
  throw this.createConnectionError(error, serverOutput);
171
170
  }
172
171
  }
173
- async pushServerBinary(serverBinPath, remoteServerPath) {
174
- await this.pushServer(serverBinPath, remoteServerPath);
175
- }
176
172
  async createScrcpyOptions() {
177
173
  const [{ AdbScrcpyOptions3_3_3 }, { ScrcpyInstanceId }] = await Promise.all([
178
174
  import("@yume-chan/adb-scrcpy"),
@@ -226,12 +222,12 @@ var __webpack_modules__ = {
226
222
  return output.filter((line)=>'string' == typeof line);
227
223
  }
228
224
  resolveServerBinPath() {
229
- const androidPkgJson = (0, node_module__rspack_import_0.createRequire)(__rslib_import_meta_url__).resolve('@midscene/android/package.json');
230
- return (0, _resource_path__rspack_import_3.J)(node_path__rspack_import_1_default().join(node_path__rspack_import_1_default().dirname(androidPkgJson), 'bin', 'scrcpy-server'));
225
+ const androidPkgJson = (0, node_module__rspack_import_1.createRequire)(__rslib_import_meta_url__).resolve('@midscene/android/package.json');
226
+ return (0, _resource_path__rspack_import_4.J)(node_path__rspack_import_2_default().join(node_path__rspack_import_2_default().dirname(androidPkgJson), 'bin', 'scrcpy-server'));
231
227
  }
232
228
  getFfmpegPath() {
233
229
  try {
234
- const dynamicRequire = (0, node_module__rspack_import_0.createRequire)(__rslib_import_meta_url__);
230
+ const dynamicRequire = (0, node_module__rspack_import_1.createRequire)(__rslib_import_meta_url__);
235
231
  const ffmpegInstaller = dynamicRequire('@ffmpeg-installer/ffmpeg');
236
232
  debugScrcpy(`Using ffmpeg from npm package: ${ffmpegInstaller.path}`);
237
233
  return ffmpegInstaller.path;
@@ -770,63 +766,36 @@ var __webpack_modules__ = {
770
766
  isConnected() {
771
767
  return this.isInitialized && null !== this.scrcpyClient;
772
768
  }
773
- constructor(adb, options = {}, pushServer = missingScrcpyServerPusher){
774
- _define_property(this, "pushServer", void 0);
769
+ constructor(adb, options = {}){
775
770
  _define_property(this, "adb", void 0);
776
- _define_property(this, "scrcpyClient", void 0);
777
- _define_property(this, "videoStream", void 0);
778
- _define_property(this, "spsHeader", void 0);
779
- _define_property(this, "idleTimer", void 0);
780
- _define_property(this, "connectionPromise", void 0);
781
- _define_property(this, "disposed", void 0);
782
- _define_property(this, "isInitialized", void 0);
771
+ _define_property(this, "scrcpyClient", null);
772
+ _define_property(this, "videoStream", null);
773
+ _define_property(this, "spsHeader", null);
774
+ _define_property(this, "idleTimer", null);
775
+ _define_property(this, "connectionPromise", null);
776
+ _define_property(this, "disposed", false);
777
+ _define_property(this, "isInitialized", false);
783
778
  _define_property(this, "options", void 0);
784
- _define_property(this, "ffmpegAvailable", void 0);
785
- _define_property(this, "keyframeResolvers", void 0);
786
- _define_property(this, "keyframeListeners", void 0);
787
- _define_property(this, "lastRawKeyframe", void 0);
788
- _define_property(this, "lastRawKeyframeAt", void 0);
779
+ _define_property(this, "ffmpegAvailable", null);
780
+ _define_property(this, "keyframeResolvers", []);
781
+ _define_property(this, "keyframeListeners", new Set());
782
+ _define_property(this, "lastRawKeyframe", null);
783
+ _define_property(this, "lastRawKeyframeAt", 0);
789
784
  _define_property(this, "lastRawKeyframePtsUs", void 0);
790
785
  _define_property(this, "lastRawKeyframeEstimatedAgeMs", void 0);
791
- _define_property(this, "videoResolution", void 0);
792
- _define_property(this, "streamReader", void 0);
793
- _define_property(this, "frameFreshnessBarrierPtsUs", void 0);
794
- _define_property(this, "frameFreshnessBarrierReason", void 0);
795
- _define_property(this, "streamStartupWindow", void 0);
796
- _define_property(this, "frameFreshnessBarrierPending", void 0);
797
- _define_property(this, "frameFreshnessBarrierGeneration", void 0);
798
- _define_property(this, "deviceClockCalibration", void 0);
799
- _define_property(this, "deviceClockCalibrationPromise", void 0);
800
- _define_property(this, "lastFramePtsUs", void 0);
801
- _define_property(this, "frameFreshnessError", void 0);
802
- _define_property(this, "lastFrameFreshnessWarningAt", void 0);
803
- _define_property(this, "disposePromise", void 0);
804
- this.pushServer = pushServer;
805
- this.scrcpyClient = null;
806
- this.videoStream = null;
807
- this.spsHeader = null;
808
- this.idleTimer = null;
809
- this.connectionPromise = null;
810
- this.disposed = false;
811
- this.isInitialized = false;
812
- this.ffmpegAvailable = null;
813
- this.keyframeResolvers = [];
814
- this.keyframeListeners = new Set();
815
- this.lastRawKeyframe = null;
816
- this.lastRawKeyframeAt = 0;
817
- this.videoResolution = null;
818
- this.streamReader = null;
819
- this.frameFreshnessBarrierPtsUs = null;
820
- this.frameFreshnessBarrierReason = null;
821
- this.streamStartupWindow = null;
822
- this.frameFreshnessBarrierPending = false;
823
- this.frameFreshnessBarrierGeneration = 0;
824
- this.deviceClockCalibration = null;
825
- this.deviceClockCalibrationPromise = null;
826
- this.lastFramePtsUs = null;
827
- this.frameFreshnessError = null;
828
- this.lastFrameFreshnessWarningAt = 0;
829
- this.disposePromise = null;
786
+ _define_property(this, "videoResolution", null);
787
+ _define_property(this, "streamReader", null);
788
+ _define_property(this, "frameFreshnessBarrierPtsUs", null);
789
+ _define_property(this, "frameFreshnessBarrierReason", null);
790
+ _define_property(this, "streamStartupWindow", null);
791
+ _define_property(this, "frameFreshnessBarrierPending", false);
792
+ _define_property(this, "frameFreshnessBarrierGeneration", 0);
793
+ _define_property(this, "deviceClockCalibration", null);
794
+ _define_property(this, "deviceClockCalibrationPromise", null);
795
+ _define_property(this, "lastFramePtsUs", null);
796
+ _define_property(this, "frameFreshnessError", null);
797
+ _define_property(this, "lastFrameFreshnessWarningAt", 0);
798
+ _define_property(this, "disposePromise", null);
830
799
  this.adb = adb;
831
800
  const requestedBitRate = options.videoBitRate ?? DEFAULT_VIDEO_BIT_RATE;
832
801
  const clampedBitRate = Math.min(requestedBitRate, MAX_VIDEO_BIT_RATE);
@@ -1089,7 +1058,7 @@ ${stdout ? truncateAdbShellStream(stdout, 'stdout') : EMPTY_ADB_SHELL_STDOUT}`;
1089
1058
  const bitRateDescription = Number.isFinite(videoBitRate) ? ` Current videoBitRate: ${videoBitRate} bps (${videoBitRate / 1000000} Mbps).` : '';
1090
1059
  return `No usable scrcpy frame crossed the active freshness target within ${timeoutMs}ms. This can happen when a static screen emits no new encoded frame, or when the video stream or transport is interrupted. This timeout does not by itself identify bandwidth or the configured video bitrate as the cause.${bitRateDescription}`;
1091
1060
  }
1092
- const DEFAULT_ADB_SERVER_CONNECTION = {
1061
+ const DEFAULT_ADB_SERVER_ENDPOINT = {
1093
1062
  host: '127.0.0.1',
1094
1063
  port: 5037
1095
1064
  };
@@ -1157,21 +1126,17 @@ ${stdout ? truncateAdbShellStream(stdout, 'stdout') : EMPTY_ADB_SHELL_STDOUT}`;
1157
1126
  const { Adb, AdbServerClient } = await import("@yume-chan/adb");
1158
1127
  const { AdbServerNodeTcpConnector } = await import("@yume-chan/adb-server-node-tcp");
1159
1128
  const { ScrcpyScreenshotManager: ScrcpyManager } = await Promise.resolve().then(__webpack_require__.bind(__webpack_require__, "./src/scrcpy-manager.ts"));
1160
- const adbServerConnection = await this.resolveAdbServerEndpoint();
1161
- const adbClient = new AdbServerClient(new AdbServerNodeTcpConnector({
1162
- host: adbServerConnection.host,
1163
- port: adbServerConnection.port
1164
- }));
1129
+ const adbServerEndpoint = await this.resolveAdbServerEndpoint();
1130
+ const adbClient = new AdbServerClient(new AdbServerNodeTcpConnector(adbServerEndpoint));
1165
1131
  adb = new Adb(await adbClient.createTransport({
1166
1132
  serial: this.deviceId
1167
1133
  }));
1168
1134
  const config = this.resolveConfig();
1169
- const serverPusher = adbServerConnection.pushServer ?? this.createDefaultServerPusher(adbServerConnection);
1170
1135
  manager = new ScrcpyManager(adb, {
1171
1136
  maxSize: config.maxSize,
1172
1137
  videoBitRate: config.videoBitRate,
1173
1138
  idleTimeoutMs: config.idleTimeoutMs
1174
- }, serverPusher);
1139
+ });
1175
1140
  await manager.validateEnvironment();
1176
1141
  if (generation !== this.lifecycleGeneration) throw new Error('Scrcpy manager initialization was superseded by device cleanup');
1177
1142
  this.manager = manager;
@@ -1195,17 +1160,6 @@ ${stdout ? truncateAdbShellStream(stdout, 'stdout') : EMPTY_ADB_SHELL_STDOUT}`;
1195
1160
  if (this.managerPromise === managerPromise) this.managerPromise = null;
1196
1161
  }
1197
1162
  }
1198
- createDefaultServerPusher(endpoint) {
1199
- let fileTransferAdb;
1200
- return async (localPath, remotePath)=>{
1201
- fileTransferAdb ??= new external_appium_adb_namespaceObject.ADB({
1202
- udid: this.deviceId,
1203
- remoteAdbHost: endpoint.host,
1204
- remoteAdbPort: endpoint.port
1205
- });
1206
- await fileTransferAdb.push(localPath, remotePath);
1207
- };
1208
- }
1209
1163
  async ensureConnectedManager(deviceInfo) {
1210
1164
  const manager = await this.ensureManager(deviceInfo);
1211
1165
  const wasConnected = manager.isConnected();
@@ -1372,7 +1326,7 @@ ${stdout ? truncateAdbShellStream(stdout, 'stdout') : EMPTY_ADB_SHELL_STDOUT}`;
1372
1326
  this.resolvedConfig = null;
1373
1327
  this.clearFailure();
1374
1328
  }
1375
- constructor(deviceId, scrcpyConfig, resolveAdbServerEndpoint = ()=>DEFAULT_ADB_SERVER_CONNECTION){
1329
+ constructor(deviceId, scrcpyConfig, resolveAdbServerEndpoint = ()=>DEFAULT_ADB_SERVER_ENDPOINT){
1376
1330
  _define_property(this, "deviceId", void 0);
1377
1331
  _define_property(this, "scrcpyConfig", void 0);
1378
1332
  _define_property(this, "resolveAdbServerEndpoint", void 0);
@@ -1892,10 +1846,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1892
1846
  const adb = await this.getAdb();
1893
1847
  return {
1894
1848
  host: adb.adbHost ?? '127.0.0.1',
1895
- port: adb.adbPort ?? 5037,
1896
- pushServer: async (localPath, remotePath)=>{
1897
- await adb.push(localPath, remotePath);
1898
- }
1849
+ port: adb.adbPort ?? 5037
1899
1850
  };
1900
1851
  });
1901
1852
  return this.scrcpyAdapter;
@@ -3269,7 +3220,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
3269
3220
  const tools = new AndroidMidsceneTools();
3270
3221
  (0, cli_namespaceObject.runToolsCLI)(tools, 'midscene-android', {
3271
3222
  stripPrefix: 'android_',
3272
- version: "1.12.1-beta-20260826131413.0",
3223
+ version: "1.12.1",
3273
3224
  extraCommands: (0, core_namespaceObject.createReportCliCommands)()
3274
3225
  }).catch((e)=>{
3275
3226
  process.exit((0, cli_namespaceObject.reportCLIError)(e));
package/dist/lib/index.js CHANGED
@@ -19,11 +19,12 @@ var __webpack_modules__ = {
19
19
  ScrcpyScreenshotManager: ()=>ScrcpyScreenshotManager,
20
20
  ov: ()=>DEFAULT_SCRCPY_CONFIG
21
21
  });
22
- var node_module__rspack_import_0 = __webpack_require__("node:module");
23
- var node_path__rspack_import_1 = __webpack_require__("node:path");
24
- var node_path__rspack_import_1_default = /*#__PURE__*/ __webpack_require__.n(node_path__rspack_import_1);
25
- var _midscene_shared_logger__rspack_import_2 = __webpack_require__("@midscene/shared/logger");
26
- var _resource_path__rspack_import_3 = __webpack_require__("./src/resource-path.ts");
22
+ var node_fs__rspack_import_0 = __webpack_require__("node:fs");
23
+ var node_module__rspack_import_1 = __webpack_require__("node:module");
24
+ var node_path__rspack_import_2 = __webpack_require__("node:path");
25
+ var node_path__rspack_import_2_default = /*#__PURE__*/ __webpack_require__.n(node_path__rspack_import_2);
26
+ var _midscene_shared_logger__rspack_import_3 = __webpack_require__("@midscene/shared/logger");
27
+ var _resource_path__rspack_import_4 = __webpack_require__("./src/resource-path.ts");
27
28
  function _define_property(obj, key, value) {
28
29
  if (key in obj) Object.defineProperty(obj, key, {
29
30
  value: value,
@@ -34,8 +35,8 @@ var __webpack_modules__ = {
34
35
  else obj[key] = value;
35
36
  return obj;
36
37
  }
37
- const debugScrcpy = (0, _midscene_shared_logger__rspack_import_2.getDebug)('android:scrcpy');
38
- const warnScrcpy = (0, _midscene_shared_logger__rspack_import_2.getDebug)('android:scrcpy', {
38
+ const debugScrcpy = (0, _midscene_shared_logger__rspack_import_3.getDebug)('android:scrcpy');
39
+ const warnScrcpy = (0, _midscene_shared_logger__rspack_import_3.getDebug)('android:scrcpy', {
39
40
  console: true
40
41
  });
41
42
  const NAL_TYPE_IDR = 5;
@@ -68,9 +69,6 @@ var __webpack_modules__ = {
68
69
  idleTimeoutMs: DEFAULT_IDLE_TIMEOUT_MS,
69
70
  videoBitRate: DEFAULT_VIDEO_BIT_RATE
70
71
  };
71
- const missingScrcpyServerPusher = async ()=>{
72
- throw new Error('Scrcpy server pusher is not configured');
73
- };
74
72
  const SCRCPY_FRESH_FRAME_UNAVAILABLE_ERROR_CODE = 'ERR_SCRCPY_FRESH_FRAME_UNAVAILABLE';
75
73
  class ScrcpyFreshFrameUnavailableError extends Error {
76
74
  constructor(message, options){
@@ -137,9 +135,10 @@ var __webpack_modules__ = {
137
135
  try {
138
136
  debugScrcpy('Starting scrcpy connection...');
139
137
  const { AdbScrcpyClient } = await import("@yume-chan/adb-scrcpy");
138
+ const { ReadableStream } = await import("@yume-chan/stream-extra");
140
139
  const { DefaultServerPath } = await import("@yume-chan/scrcpy");
141
140
  const serverBinPath = this.resolveServerBinPath();
142
- await this.pushServerBinary(serverBinPath, DefaultServerPath);
141
+ await AdbScrcpyClient.pushServer(this.adb, ReadableStream.from((0, node_fs__rspack_import_0.createReadStream)(serverBinPath)));
143
142
  const scrcpyOptions = await this.createScrcpyOptions();
144
143
  await this.ensureFrameClockCalibration();
145
144
  this.scrcpyClient = await AdbScrcpyClient.start(this.adb, DefaultServerPath, scrcpyOptions);
@@ -170,9 +169,6 @@ var __webpack_modules__ = {
170
169
  throw this.createConnectionError(error, serverOutput);
171
170
  }
172
171
  }
173
- async pushServerBinary(serverBinPath, remoteServerPath) {
174
- await this.pushServer(serverBinPath, remoteServerPath);
175
- }
176
172
  async createScrcpyOptions() {
177
173
  const [{ AdbScrcpyOptions3_3_3 }, { ScrcpyInstanceId }] = await Promise.all([
178
174
  import("@yume-chan/adb-scrcpy"),
@@ -226,12 +222,12 @@ var __webpack_modules__ = {
226
222
  return output.filter((line)=>'string' == typeof line);
227
223
  }
228
224
  resolveServerBinPath() {
229
- const androidPkgJson = (0, node_module__rspack_import_0.createRequire)(__rslib_import_meta_url__).resolve('@midscene/android/package.json');
230
- return (0, _resource_path__rspack_import_3.J)(node_path__rspack_import_1_default().join(node_path__rspack_import_1_default().dirname(androidPkgJson), 'bin', 'scrcpy-server'));
225
+ const androidPkgJson = (0, node_module__rspack_import_1.createRequire)(__rslib_import_meta_url__).resolve('@midscene/android/package.json');
226
+ return (0, _resource_path__rspack_import_4.J)(node_path__rspack_import_2_default().join(node_path__rspack_import_2_default().dirname(androidPkgJson), 'bin', 'scrcpy-server'));
231
227
  }
232
228
  getFfmpegPath() {
233
229
  try {
234
- const dynamicRequire = (0, node_module__rspack_import_0.createRequire)(__rslib_import_meta_url__);
230
+ const dynamicRequire = (0, node_module__rspack_import_1.createRequire)(__rslib_import_meta_url__);
235
231
  const ffmpegInstaller = dynamicRequire('@ffmpeg-installer/ffmpeg');
236
232
  debugScrcpy(`Using ffmpeg from npm package: ${ffmpegInstaller.path}`);
237
233
  return ffmpegInstaller.path;
@@ -770,63 +766,36 @@ var __webpack_modules__ = {
770
766
  isConnected() {
771
767
  return this.isInitialized && null !== this.scrcpyClient;
772
768
  }
773
- constructor(adb, options = {}, pushServer = missingScrcpyServerPusher){
774
- _define_property(this, "pushServer", void 0);
769
+ constructor(adb, options = {}){
775
770
  _define_property(this, "adb", void 0);
776
- _define_property(this, "scrcpyClient", void 0);
777
- _define_property(this, "videoStream", void 0);
778
- _define_property(this, "spsHeader", void 0);
779
- _define_property(this, "idleTimer", void 0);
780
- _define_property(this, "connectionPromise", void 0);
781
- _define_property(this, "disposed", void 0);
782
- _define_property(this, "isInitialized", void 0);
771
+ _define_property(this, "scrcpyClient", null);
772
+ _define_property(this, "videoStream", null);
773
+ _define_property(this, "spsHeader", null);
774
+ _define_property(this, "idleTimer", null);
775
+ _define_property(this, "connectionPromise", null);
776
+ _define_property(this, "disposed", false);
777
+ _define_property(this, "isInitialized", false);
783
778
  _define_property(this, "options", void 0);
784
- _define_property(this, "ffmpegAvailable", void 0);
785
- _define_property(this, "keyframeResolvers", void 0);
786
- _define_property(this, "keyframeListeners", void 0);
787
- _define_property(this, "lastRawKeyframe", void 0);
788
- _define_property(this, "lastRawKeyframeAt", void 0);
779
+ _define_property(this, "ffmpegAvailable", null);
780
+ _define_property(this, "keyframeResolvers", []);
781
+ _define_property(this, "keyframeListeners", new Set());
782
+ _define_property(this, "lastRawKeyframe", null);
783
+ _define_property(this, "lastRawKeyframeAt", 0);
789
784
  _define_property(this, "lastRawKeyframePtsUs", void 0);
790
785
  _define_property(this, "lastRawKeyframeEstimatedAgeMs", void 0);
791
- _define_property(this, "videoResolution", void 0);
792
- _define_property(this, "streamReader", void 0);
793
- _define_property(this, "frameFreshnessBarrierPtsUs", void 0);
794
- _define_property(this, "frameFreshnessBarrierReason", void 0);
795
- _define_property(this, "streamStartupWindow", void 0);
796
- _define_property(this, "frameFreshnessBarrierPending", void 0);
797
- _define_property(this, "frameFreshnessBarrierGeneration", void 0);
798
- _define_property(this, "deviceClockCalibration", void 0);
799
- _define_property(this, "deviceClockCalibrationPromise", void 0);
800
- _define_property(this, "lastFramePtsUs", void 0);
801
- _define_property(this, "frameFreshnessError", void 0);
802
- _define_property(this, "lastFrameFreshnessWarningAt", void 0);
803
- _define_property(this, "disposePromise", void 0);
804
- this.pushServer = pushServer;
805
- this.scrcpyClient = null;
806
- this.videoStream = null;
807
- this.spsHeader = null;
808
- this.idleTimer = null;
809
- this.connectionPromise = null;
810
- this.disposed = false;
811
- this.isInitialized = false;
812
- this.ffmpegAvailable = null;
813
- this.keyframeResolvers = [];
814
- this.keyframeListeners = new Set();
815
- this.lastRawKeyframe = null;
816
- this.lastRawKeyframeAt = 0;
817
- this.videoResolution = null;
818
- this.streamReader = null;
819
- this.frameFreshnessBarrierPtsUs = null;
820
- this.frameFreshnessBarrierReason = null;
821
- this.streamStartupWindow = null;
822
- this.frameFreshnessBarrierPending = false;
823
- this.frameFreshnessBarrierGeneration = 0;
824
- this.deviceClockCalibration = null;
825
- this.deviceClockCalibrationPromise = null;
826
- this.lastFramePtsUs = null;
827
- this.frameFreshnessError = null;
828
- this.lastFrameFreshnessWarningAt = 0;
829
- this.disposePromise = null;
786
+ _define_property(this, "videoResolution", null);
787
+ _define_property(this, "streamReader", null);
788
+ _define_property(this, "frameFreshnessBarrierPtsUs", null);
789
+ _define_property(this, "frameFreshnessBarrierReason", null);
790
+ _define_property(this, "streamStartupWindow", null);
791
+ _define_property(this, "frameFreshnessBarrierPending", false);
792
+ _define_property(this, "frameFreshnessBarrierGeneration", 0);
793
+ _define_property(this, "deviceClockCalibration", null);
794
+ _define_property(this, "deviceClockCalibrationPromise", null);
795
+ _define_property(this, "lastFramePtsUs", null);
796
+ _define_property(this, "frameFreshnessError", null);
797
+ _define_property(this, "lastFrameFreshnessWarningAt", 0);
798
+ _define_property(this, "disposePromise", null);
830
799
  this.adb = adb;
831
800
  const requestedBitRate = options.videoBitRate ?? DEFAULT_VIDEO_BIT_RATE;
832
801
  const clampedBitRate = Math.min(requestedBitRate, MAX_VIDEO_BIT_RATE);
@@ -1010,7 +979,7 @@ ${stdout ? truncateAdbShellStream(stdout, 'stdout') : EMPTY_ADB_SHELL_STDOUT}`;
1010
979
  const bitRateDescription = Number.isFinite(videoBitRate) ? ` Current videoBitRate: ${videoBitRate} bps (${videoBitRate / 1000000} Mbps).` : '';
1011
980
  return `No usable scrcpy frame crossed the active freshness target within ${timeoutMs}ms. This can happen when a static screen emits no new encoded frame, or when the video stream or transport is interrupted. This timeout does not by itself identify bandwidth or the configured video bitrate as the cause.${bitRateDescription}`;
1012
981
  }
1013
- const DEFAULT_ADB_SERVER_CONNECTION = {
982
+ const DEFAULT_ADB_SERVER_ENDPOINT = {
1014
983
  host: '127.0.0.1',
1015
984
  port: 5037
1016
985
  };
@@ -1078,21 +1047,17 @@ ${stdout ? truncateAdbShellStream(stdout, 'stdout') : EMPTY_ADB_SHELL_STDOUT}`;
1078
1047
  const { Adb, AdbServerClient } = await import("@yume-chan/adb");
1079
1048
  const { AdbServerNodeTcpConnector } = await import("@yume-chan/adb-server-node-tcp");
1080
1049
  const { ScrcpyScreenshotManager: ScrcpyManager } = await Promise.resolve().then(__webpack_require__.bind(__webpack_require__, "./src/scrcpy-manager.ts"));
1081
- const adbServerConnection = await this.resolveAdbServerEndpoint();
1082
- const adbClient = new AdbServerClient(new AdbServerNodeTcpConnector({
1083
- host: adbServerConnection.host,
1084
- port: adbServerConnection.port
1085
- }));
1050
+ const adbServerEndpoint = await this.resolveAdbServerEndpoint();
1051
+ const adbClient = new AdbServerClient(new AdbServerNodeTcpConnector(adbServerEndpoint));
1086
1052
  adb = new Adb(await adbClient.createTransport({
1087
1053
  serial: this.deviceId
1088
1054
  }));
1089
1055
  const config = this.resolveConfig();
1090
- const serverPusher = adbServerConnection.pushServer ?? this.createDefaultServerPusher(adbServerConnection);
1091
1056
  manager = new ScrcpyManager(adb, {
1092
1057
  maxSize: config.maxSize,
1093
1058
  videoBitRate: config.videoBitRate,
1094
1059
  idleTimeoutMs: config.idleTimeoutMs
1095
- }, serverPusher);
1060
+ });
1096
1061
  await manager.validateEnvironment();
1097
1062
  if (generation !== this.lifecycleGeneration) throw new Error('Scrcpy manager initialization was superseded by device cleanup');
1098
1063
  this.manager = manager;
@@ -1116,17 +1081,6 @@ ${stdout ? truncateAdbShellStream(stdout, 'stdout') : EMPTY_ADB_SHELL_STDOUT}`;
1116
1081
  if (this.managerPromise === managerPromise) this.managerPromise = null;
1117
1082
  }
1118
1083
  }
1119
- createDefaultServerPusher(endpoint) {
1120
- let fileTransferAdb;
1121
- return async (localPath, remotePath)=>{
1122
- fileTransferAdb ??= new external_appium_adb_namespaceObject.ADB({
1123
- udid: this.deviceId,
1124
- remoteAdbHost: endpoint.host,
1125
- remoteAdbPort: endpoint.port
1126
- });
1127
- await fileTransferAdb.push(localPath, remotePath);
1128
- };
1129
- }
1130
1084
  async ensureConnectedManager(deviceInfo) {
1131
1085
  const manager = await this.ensureManager(deviceInfo);
1132
1086
  const wasConnected = manager.isConnected();
@@ -1293,7 +1247,7 @@ ${stdout ? truncateAdbShellStream(stdout, 'stdout') : EMPTY_ADB_SHELL_STDOUT}`;
1293
1247
  this.resolvedConfig = null;
1294
1248
  this.clearFailure();
1295
1249
  }
1296
- constructor(deviceId, scrcpyConfig, resolveAdbServerEndpoint = ()=>DEFAULT_ADB_SERVER_CONNECTION){
1250
+ constructor(deviceId, scrcpyConfig, resolveAdbServerEndpoint = ()=>DEFAULT_ADB_SERVER_ENDPOINT){
1297
1251
  _define_property(this, "deviceId", void 0);
1298
1252
  _define_property(this, "scrcpyConfig", void 0);
1299
1253
  _define_property(this, "resolveAdbServerEndpoint", void 0);
@@ -1813,10 +1767,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1813
1767
  const adb = await this.getAdb();
1814
1768
  return {
1815
1769
  host: adb.adbHost ?? '127.0.0.1',
1816
- port: adb.adbPort ?? 5037,
1817
- pushServer: async (localPath, remotePath)=>{
1818
- await adb.push(localPath, remotePath);
1819
- }
1770
+ port: adb.adbPort ?? 5037
1820
1771
  };
1821
1772
  });
1822
1773
  return this.scrcpyAdapter;
@@ -23,10 +23,9 @@ import { UITreeSnapshot } from '@midscene/core';
23
23
 
24
24
  declare type ActionArgs<T extends DeviceAction> = [ActionParam<T>] extends [undefined] ? [] : [ActionParam<T>];
25
25
 
26
- declare interface AdbServerConnection {
26
+ declare interface AdbServerEndpoint {
27
27
  host: string;
28
28
  port: number;
29
- pushServer?: ScrcpyServerPusher;
30
29
  }
31
30
 
32
31
  export declare function agentFromAdbDevice(deviceId?: string, opts?: AndroidAgentOpt & AndroidDeviceOpt): Promise<AndroidAgent>;
@@ -394,7 +393,7 @@ declare interface RawKeyframe {
394
393
  capturedAt: number;
395
394
  }
396
395
 
397
- declare type ResolveAdbServerConnection = () => AdbServerConnection | Promise<AdbServerConnection>;
396
+ declare type ResolveAdbServerEndpoint = () => AdbServerEndpoint | Promise<AdbServerEndpoint>;
398
397
 
399
398
  declare interface ResolvedScrcpyConfig {
400
399
  enabled: boolean;
@@ -435,7 +434,7 @@ export declare class ScrcpyDeviceAdapter {
435
434
  private pendingActionBarrierAtHostUs;
436
435
  private keyframeListeners;
437
436
  private keyframeUnsubscribers;
438
- constructor(deviceId: string, scrcpyConfig: ScrcpyConfig | undefined, resolveAdbServerEndpoint?: ResolveAdbServerConnection);
437
+ constructor(deviceId: string, scrcpyConfig: ScrcpyConfig | undefined, resolveAdbServerEndpoint?: ResolveAdbServerEndpoint);
439
438
  isEnabled(): boolean;
440
439
  getStatus(): ScrcpyStatus;
441
440
  private isConfigured;
@@ -463,7 +462,6 @@ export declare class ScrcpyDeviceAdapter {
463
462
  * Uses dynamic import for @yume-chan packages (ESM-only, must use await import in CJS builds).
464
463
  */
465
464
  ensureManager(_deviceInfo: DevicePhysicalInfo): Promise<ScrcpyScreenshotManager>;
466
- private createDefaultServerPusher;
467
465
  /**
468
466
  * Connect the current manager and restore adapter-owned frame subscriptions
469
467
  * whenever this call establishes a new stream epoch. Existing connections
@@ -529,7 +527,6 @@ declare interface ScrcpyFreshnessBarrierOptions {
529
527
  }
530
528
 
531
529
  declare class ScrcpyScreenshotManager {
532
- private readonly pushServer;
533
530
  private adb;
534
531
  private scrcpyClient;
535
532
  private videoStream;
@@ -559,7 +556,7 @@ declare class ScrcpyScreenshotManager {
559
556
  private frameFreshnessError;
560
557
  private lastFrameFreshnessWarningAt;
561
558
  private disposePromise;
562
- constructor(adb: Adb, options?: ScrcpyScreenshotOptions, pushServer?: ScrcpyServerPusher);
559
+ constructor(adb: Adb, options?: ScrcpyScreenshotOptions);
563
560
  /**
564
561
  * Validate environment prerequisites (ffmpeg, scrcpy-server, etc.)
565
562
  * Must be called once after construction, before any screenshot operations.
@@ -571,7 +568,6 @@ declare class ScrcpyScreenshotManager {
571
568
  */
572
569
  ensureConnected(): Promise<void>;
573
570
  private connectScrcpy;
574
- private pushServerBinary;
575
571
  private createScrcpyOptions;
576
572
  private collectServerOutput;
577
573
  private createConnectionError;
@@ -723,9 +719,6 @@ declare interface ScrcpyScreenshotOptions {
723
719
  idleTimeoutMs?: number;
724
720
  }
725
721
 
726
- /** Transfers the local scrcpy server binary to its device path. */
727
- declare type ScrcpyServerPusher = (localPath: string, remotePath: string) => Promise<void>;
728
-
729
722
  export declare interface ScrcpyStatus {
730
723
  enabled: boolean;
731
724
  connected: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@midscene/android",
3
- "version": "1.12.1-beta-20260826131413.0",
3
+ "version": "1.12.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/web-infra-dev/midscene.git",
@@ -41,8 +41,8 @@
41
41
  "@yume-chan/stream-extra": "2.6.1",
42
42
  "appium-adb": "12.12.1",
43
43
  "sharp": "^0.34.3",
44
- "@midscene/core": "1.12.1-beta-20260826131413.0",
45
- "@midscene/shared": "1.12.1-beta-20260826131413.0"
44
+ "@midscene/shared": "1.12.1",
45
+ "@midscene/core": "1.12.1"
46
46
  },
47
47
  "optionalDependencies": {
48
48
  "@ffmpeg-installer/ffmpeg": "^1.1.0"
@@ -56,7 +56,7 @@
56
56
  "typescript": "^5.8.3",
57
57
  "undici": "^6.0.0",
58
58
  "zod": "^3.25.1",
59
- "@midscene/playground": "1.12.1-beta-20260826131413.0"
59
+ "@midscene/playground": "1.12.1"
60
60
  },
61
61
  "license": "MIT",
62
62
  "scripts": {