@midscene/android 1.12.0 → 1.12.1-beta-20260824081858.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -336,6 +336,7 @@ export declare class AndroidDevice implements AbstractInterface {
336
336
 
337
337
  declare type AndroidInitArgs = AgentBehaviorInitArgs & {
338
338
  deviceId?: string;
339
+ scrcpyVideoBitRate?: number;
339
340
  useScrcpy?: boolean;
340
341
  };
341
342
 
@@ -425,13 +426,15 @@ export declare class ScrcpyDeviceAdapter {
425
426
  private scrcpyConfig;
426
427
  private resolveAdbServerEndpoint;
427
428
  private manager;
429
+ private managerPromise;
428
430
  private resolvedConfig;
429
431
  private lastError;
430
432
  private retryAfter;
431
433
  private freshnessRecoveryPending;
434
+ private freshnessRestartPromise;
432
435
  private recoveryPromise;
433
436
  private lifecycleGeneration;
434
- private pendingActionBarrier;
437
+ private pendingActionBarrierAtHostUs;
435
438
  private keyframeListeners;
436
439
  private keyframeUnsubscribers;
437
440
  constructor(deviceId: string, scrcpyConfig: ScrcpyConfig | undefined, resolveAdbServerEndpoint?: ResolveAdbServerEndpoint);
@@ -451,7 +454,15 @@ export declare class ScrcpyDeviceAdapter {
451
454
  * receives the highest quality image for AI processing.
452
455
  * videoBitRate uses the shared default unless explicitly configured.
453
456
  */
454
- resolveConfig(deviceInfo: DevicePhysicalInfo): ResolvedScrcpyConfig;
457
+ resolveConfig(_deviceInfo?: DevicePhysicalInfo): ResolvedScrcpyConfig;
458
+ /**
459
+ * Apply the configured scrcpy video bound to an independently captured
460
+ * fallback screenshot. This prevents planning and report images from returning
461
+ * to full device resolution while the scrcpy stream is temporarily unavailable.
462
+ * The bound only applies when scrcpy is configured as enabled; disabling
463
+ * scrcpy preserves the existing ADB/yadb screenshot behavior.
464
+ */
465
+ prepareFallbackScreenshot(screenshotBase64: string): Promise<string>;
455
466
  /**
456
467
  * Get or create the ScrcpyScreenshotManager.
457
468
  * Uses dynamic import for @yume-chan packages (ESM-only, must use await import in CJS builds).
@@ -459,9 +470,14 @@ export declare class ScrcpyDeviceAdapter {
459
470
  ensureManager(deviceInfo: DevicePhysicalInfo): Promise<ScrcpyScreenshotManager>;
460
471
  /**
461
472
  * Take a screenshot via scrcpy, returns base64 string.
462
- * Throws on failure (caller should fallback to ADB).
473
+ * A stale established stream is restarted once so a static screen can use
474
+ * the new epoch's baseline frame. Throws only when that retry also fails, so
475
+ * the caller can fall back to ADB.
463
476
  */
464
477
  screenshotBase64(deviceInfo: DevicePhysicalInfo): Promise<string>;
478
+ private restartAndCaptureOnce;
479
+ private jpegBufferToBase64;
480
+ private warnFreshnessFallback;
465
481
  /**
466
482
  * Subscribe to raw keyframes from the scrcpy stream (ensures the stream is
467
483
  * connected first). Frames are raw H.264 — no decoding cost. While
@@ -475,6 +491,8 @@ export declare class ScrcpyDeviceAdapter {
475
491
  private attachKeyframeListeners;
476
492
  private markFreshnessRecoveryPending;
477
493
  private applyPendingActionBarrier;
494
+ private monotonicTimeUs;
495
+ private deferActionBarrier;
478
496
  /**
479
497
  * Start a new scrcpy epoch only after the independent ADB screenshot has
480
498
  * completed, so stream startup does not compete with the fallback capture.
@@ -511,13 +529,19 @@ export declare class ScrcpyDeviceAdapter {
511
529
  disconnect(): Promise<void>;
512
530
  }
513
531
 
532
+ declare interface ScrcpyFreshnessBarrierOptions {
533
+ hostMonotonicUs?: bigint;
534
+ allowOverAgeForNextCapture?: boolean;
535
+ }
536
+
514
537
  declare class ScrcpyScreenshotManager {
515
538
  private adb;
516
539
  private scrcpyClient;
517
540
  private videoStream;
518
541
  private spsHeader;
519
542
  private idleTimer;
520
- private isConnecting;
543
+ private connectionPromise;
544
+ private disposed;
521
545
  private isInitialized;
522
546
  private options;
523
547
  private ffmpegAvailable;
@@ -531,6 +555,9 @@ declare class ScrcpyScreenshotManager {
531
555
  private streamReader;
532
556
  private frameFreshnessBarrierPtsUs;
533
557
  private frameFreshnessBarrierReason;
558
+ private frameFreshnessBarrierAllowsOverAgeForNextCapture;
559
+ private streamBaselineFramePending;
560
+ private streamBaselineFrameDeadlineAt;
534
561
  private frameFreshnessBarrierPending;
535
562
  private frameFreshnessBarrierGeneration;
536
563
  private deviceClockCalibration;
@@ -550,6 +577,7 @@ declare class ScrcpyScreenshotManager {
550
577
  * Ensure scrcpy connection is active
551
578
  */
552
579
  ensureConnected(): Promise<void>;
580
+ private connectScrcpy;
553
581
  private createScrcpyOptions;
554
582
  private collectServerOutput;
555
583
  private createConnectionError;
@@ -592,10 +620,14 @@ declare class ScrcpyScreenshotManager {
592
620
  /**
593
621
  * Invalidate cached frames and require future packets to be captured after
594
622
  * the host-monotonic action/planning boundary projected onto the device
595
- * clock. The projection reuses the single calibration for this stream epoch
596
- * and does not issue another ADB clock read.
597
- */
598
- setFreshnessBarrier(reason: string): Promise<bigint>;
623
+ * clock. A caller recovering an unavailable stream can pass the original
624
+ * action-boundary timestamp so connection startup latency does not move the
625
+ * barrier forward. Action barriers may allow the first proven post-boundary
626
+ * frame to survive a long wait-after-action delay. The projection reuses the
627
+ * single calibration for this stream epoch and does not issue another ADB
628
+ * clock read.
629
+ */
630
+ setFreshnessBarrier(reason: string, options?: ScrcpyFreshnessBarrierOptions): Promise<bigint>;
599
631
  private isFrameFresh;
600
632
  private estimateFrameAgeUs;
601
633
  private estimateFrameAge;
@@ -603,9 +635,11 @@ declare class ScrcpyScreenshotManager {
603
635
  private getCalibrationUncertaintyUs;
604
636
  private isFrameAgeAcceptable;
605
637
  private warnFrameFreshness;
638
+ private transportBacklogMessage;
606
639
  private warnTransportBacklog;
607
640
  private estimateFrameTiming;
608
641
  private clearFrameCache;
642
+ private restoreFrameCache;
609
643
  private monotonicTimeUs;
610
644
  private resetFrameFreshnessState;
611
645
  /**
@@ -620,6 +654,9 @@ declare class ScrcpyScreenshotManager {
620
654
  /** Latest raw keyframe seen on the stream, or null if none yet. */
621
655
  getLatestRawKeyframe(): RawKeyframe | null;
622
656
  private getCachedKeyframeCandidate;
657
+ private canReuseFrameAcrossActionWait;
658
+ private canUseStreamBaseline;
659
+ private consumeActionFreshnessBarrier;
623
660
  /**
624
661
  * Decode a raw keyframe (from {@link subscribeKeyframes} or
625
662
  * {@link getLatestRawKeyframe}) to a JPEG buffer. This is the deferred,
@@ -627,20 +664,24 @@ declare class ScrcpyScreenshotManager {
627
664
  * sampled frames, never inside a capture loop.
628
665
  */
629
666
  decodeRawKeyframeToJpeg(frame: RawKeyframe): Promise<Buffer>;
630
- private waitForUsableKeyframe;
631
667
  /**
632
- * Ensure a newly connected stream has a calibrated, temporally fresh frame
633
- * before it is exposed again after ADB fallback.
668
+ * Ensure a newly connected stream has a calibrated, usable epoch baseline
669
+ * or a frame that crossed its active action barrier before exposing it again
670
+ * after ADB fallback.
634
671
  */
635
672
  prepareFreshFrame(): Promise<void>;
636
673
  private waitForPlanningFrame;
637
674
  private closeStaleStreamAndCreateFallbackError;
638
675
  /**
639
676
  * Get screenshot as JPEG.
640
- * Reuses a frame only when it crossed the active action barrier and its
641
- * absolute age is within the accepted limit. An over-age candidate arms a
642
- * planning barrier on demand. If no frame crosses the resulting freshness
643
- * target in time, close this stream epoch and let the caller use ADB.
677
+ * A newly connected stream may use its first epoch-local frame once during
678
+ * the bounded startup window, because a static screen will not emit another
679
+ * frame after clock calibration completes.
680
+ * Reuses one frame that crossed the active input-action barrier even if a
681
+ * long wait-after-action made its absolute age exceed the planning limit.
682
+ * Other over-age candidates arm a planning barrier on demand. If no frame
683
+ * crosses the resulting freshness target in time, close this stream epoch
684
+ * and let the caller use ADB.
644
685
  */
645
686
  getScreenshotJpeg(): Promise<Buffer>;
646
687
  /**
@@ -687,6 +728,11 @@ declare class ScrcpyScreenshotManager {
687
728
  * Disconnect scrcpy
688
729
  */
689
730
  disconnect(): Promise<void>;
731
+ /**
732
+ * Permanently release the scrcpy stream and the owned yume ADB transport.
733
+ * Unlike disconnect(), a disposed manager cannot be reconnected.
734
+ */
735
+ dispose(): Promise<void>;
690
736
  /**
691
737
  * Check if scrcpy is initialized and connected
692
738
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@midscene/android",
3
- "version": "1.12.0",
3
+ "version": "1.12.1-beta-20260824081858.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/web-infra-dev/midscene.git",
@@ -34,15 +34,15 @@
34
34
  "./package.json": "./package.json"
35
35
  },
36
36
  "dependencies": {
37
- "@yume-chan/adb": "2.5.1",
37
+ "@yume-chan/adb": "2.6.3",
38
38
  "@yume-chan/adb-scrcpy": "2.3.2",
39
39
  "@yume-chan/adb-server-node-tcp": "2.5.2",
40
40
  "@yume-chan/scrcpy": "2.3.0",
41
- "@yume-chan/stream-extra": "2.1.0",
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.0",
45
- "@midscene/shared": "1.12.0"
44
+ "@midscene/core": "1.12.1-beta-20260824081858.0",
45
+ "@midscene/shared": "1.12.1-beta-20260824081858.0"
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.0"
59
+ "@midscene/playground": "1.12.1-beta-20260824081858.0"
60
60
  },
61
61
  "license": "MIT",
62
62
  "scripts": {