VirtualDesktop 1.6.4__tar.gz → 1.6.6__tar.gz
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.
- virtualdesktop-1.6.6/MANIFEST.in +7 -0
- {virtualdesktop-1.6.4/VirtualDesktop.egg-info → virtualdesktop-1.6.6}/PKG-INFO +89 -6
- virtualdesktop-1.6.4/PKG-INFO → virtualdesktop-1.6.6/README.md +787 -763
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/record.py +49 -3
- virtualdesktop-1.6.4/README.md → virtualdesktop-1.6.6/VirtualDesktop.egg-info/PKG-INFO +846 -706
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop.egg-info/SOURCES.txt +1 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop.egg-info/requires.txt +3 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/pyproject.toml +10 -5
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/tests/test_packaging.py +59 -2
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/LICENSE +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/__init__.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/__main__.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/_bundle.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/_compat.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/_desktop_runtime.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/_devices.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/_download.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/_enumerate.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/_helper.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/_log.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/_process.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/_sigcheck.ps1 +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/_sigcheck.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/_winapi.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/agent.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/capture.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/cli.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/config.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/desktop.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/desktop_capture.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/desktop_session.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/display_setup.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/driver.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/driver_manifest.json +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/errors.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/manifest.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/session.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/window.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop/workspace.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop.egg-info/dependency_links.txt +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop.egg-info/entry_points.txt +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/VirtualDesktop.egg-info/top_level.txt +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/setup.cfg +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/tests/test_accelerators.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/tests/test_agent.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/tests/test_artifact_regression.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/tests/test_capture.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/tests/test_cli.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/tests/test_compat.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/tests/test_config_and_winapi.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/tests/test_desktop_isolation.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/tests/test_destructive_lifecycle.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/tests/test_display_setup.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/tests/test_download.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/tests/test_driver.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/tests/test_hide_modes.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/tests/test_integration_windows.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/tests/test_manifest.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/tests/test_no_dialogs.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/tests/test_process.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/tests/test_record.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/tests/test_virtual_desktop.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/tests/test_workspace.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/tests/test_workspace_instances.py +0 -0
- {virtualdesktop-1.6.4 → virtualdesktop-1.6.6}/tests/test_workspace_move.py +0 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# The sdist is the pure-Python source distribution, and only the source distribution. The gyan.dev
|
|
2
|
+
# ffmpeg build is 84 MB of GPLv3 object code that this project redistributes only inside the
|
|
3
|
+
# platform wheel, where it is the point of the exercise; nobody installing a tarball expects to pull
|
|
4
|
+
# it down, and anybody who wants it can run ``python tools/vendor_ffmpeg.py``.
|
|
5
|
+
exclude VirtualDesktop/_vendor/ffmpeg.exe
|
|
6
|
+
exclude VirtualDesktop/_vendor/FFMPEG-LICENSE.txt
|
|
7
|
+
prune VirtualDesktop/_vendor
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: VirtualDesktop
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.6
|
|
4
4
|
Summary: win10-win11 虚拟桌面
|
|
5
5
|
Author: VirtualDesktop contributors
|
|
6
6
|
License: MIT License
|
|
@@ -53,6 +53,8 @@ Requires-Dist: pytest>=7.0; extra == "test"
|
|
|
53
53
|
Provides-Extra: build
|
|
54
54
|
Requires-Dist: build>=1.0; extra == "build"
|
|
55
55
|
Requires-Dist: twine>=5.0; extra == "build"
|
|
56
|
+
Provides-Extra: ffmpeg
|
|
57
|
+
Requires-Dist: imageio-ffmpeg>=0.4.9; extra == "ffmpeg"
|
|
56
58
|
Dynamic: license-file
|
|
57
59
|
|
|
58
60
|
# VirtualDesktop
|
|
@@ -81,10 +83,39 @@ pip install VirtualDesktop # pip
|
|
|
81
83
|
uv add VirtualDesktop # uv(写入 pyproject.toml 并锁定)
|
|
82
84
|
```
|
|
83
85
|
|
|
86
|
+
64 位 Windows 会拿到带 ffmpeg 的 `py3-none-win_amd64` wheel,录制视频开箱即用;其他平台拿到纯 Python
|
|
87
|
+
wheel,需要时再补 `pip install "VirtualDesktop[ffmpeg]"`,详见「输出格式」。
|
|
88
|
+
|
|
84
89
|
运行时依赖:**Pillow**(帧图像)与 **comtypes**(UI Automation 是 COM API)。不需要 pywin32——
|
|
85
90
|
库访问 Win32 全部走 ctypes。若国内镜像同步滞后导致找不到最新版,加
|
|
86
91
|
`--default-index https://pypi.org/simple`(uv)或 `-i https://pypi.org/simple`(pip)。
|
|
87
92
|
|
|
93
|
+
## 平台支持
|
|
94
|
+
|
|
95
|
+
**仅 Windows**,这是硬性的:整套机制建立在 `CreateDesktopW`、IddCx 驱动、`PrintWindow`、
|
|
96
|
+
UI Automation 这些 Win32/WinRT 接口上,没有跨平台对应物。
|
|
97
|
+
|
|
98
|
+
| 项目 | 支持范围 |
|
|
99
|
+
|---|---|
|
|
100
|
+
| 操作系统 | **Windows 10 1809 (build 17763) 及以上**,含 Windows 11 |
|
|
101
|
+
| CPU 类型 | **x64** 为主要目标;**ARM64** 可用(驱动清单提供 ARM64 变体,自动选用) |
|
|
102
|
+
| Python | **3.9 或更高**(`requires-python >= 3.9`;3.9–3.12 均有分类器声明) |
|
|
103
|
+
| 位数 | 64 位 Python。32 位 Python 未测试 |
|
|
104
|
+
|
|
105
|
+
各功能的最低要求不同,按需选择:
|
|
106
|
+
|
|
107
|
+
| 功能 | 最低要求 |
|
|
108
|
+
|---|---|
|
|
109
|
+
| 私有桌面、窗口消息驱动、窗口截图/录制 | Win10 任意版本,**无驱动、不提权** |
|
|
110
|
+
| `hide_mode="offscreen"` | Win10 任意版本,**无驱动** |
|
|
111
|
+
| 虚拟显示器(`virtual_screen`、桌面截图、桌面录制) | **Win10 1809 (17763)** —— 更低版本没有 IddCx 框架,装不了驱动 |
|
|
112
|
+
| 视频录制(`.mp4` 等) | 需要 ffmpeg:**64 位 Windows 由 wheel 自带**,其他平台见「输出格式」;GIF 与帧序列不需要 |
|
|
113
|
+
|
|
114
|
+
**体系结构说明**:只有虚拟显示器驱动区分体系结构,库会自动从清单里选用匹配的变体(ARM64 用
|
|
115
|
+
ARM64 包,x64/x86 共用同一份)。ffmpeg 也**分体系结构**:只有 x64 有现成构建,因此只有
|
|
116
|
+
`py3-none-win_amd64` wheel 内嵌了它,ARM64 / 32 位请用 `pip install "VirtualDesktop[ffmpeg]"`,
|
|
117
|
+
或自备二进制、或改用 `.gif`。
|
|
118
|
+
|
|
88
119
|
| | 私有桌面 | 虚拟显示器 |
|
|
89
120
|
|---|---|---|
|
|
90
121
|
| 一句话 | 另开一个桌面,窗口与你的桌面完全隔离 | 多一块屏幕,窗口仍在你的桌面上、只是画在看不见的地方 |
|
|
@@ -534,7 +565,8 @@ with VirtualWorkspace("lab") as space, space.agent() as agent:
|
|
|
534
565
|
|
|
535
566
|
### 输出格式
|
|
536
567
|
|
|
537
|
-
|
|
568
|
+
扩展名决定格式。**GIF 与帧序列只依赖 Pillow**(永远可用);**视频需要 ffmpeg**,64 位 Windows 上由
|
|
569
|
+
wheel 自带:
|
|
538
570
|
|
|
539
571
|
| 扩展名 | 写入方 | 说明 |
|
|
540
572
|
|---|---|---|
|
|
@@ -542,13 +574,59 @@ with VirtualWorkspace("lab") as space, space.agent() as agent:
|
|
|
542
574
|
| `.gif` | Pillow | 动画 GIF;`quality` 映射到调色板颜色数(8–256) |
|
|
543
575
|
| `.png` `.jpg` `.webp` … | Pillow | 写成**目录下的编号帧**,另附 `frames.json` |
|
|
544
576
|
|
|
545
|
-
|
|
577
|
+
查当前环境支持情况(用与录制相同的查找逻辑,所以报的可用性可信):
|
|
546
578
|
|
|
547
579
|
```python
|
|
548
580
|
from VirtualDesktop import supported_formats
|
|
549
|
-
print(supported_formats())
|
|
581
|
+
print(supported_formats()[".mp4"]) # 'ffmpeg (C:\...\ffmpeg.exe)' 或 'unavailable (...)'
|
|
550
582
|
```
|
|
551
583
|
|
|
584
|
+
#### ffmpeg 从哪来
|
|
585
|
+
|
|
586
|
+
**64 位 Windows 上不用管**:`pip install VirtualDesktop` 装的 `py3-none-win_amd64` wheel 里**已经带了
|
|
587
|
+
ffmpeg**,录 `.mp4` 直接就能用,不需要再下载任何东西、也不需要配 `PATH`。
|
|
588
|
+
|
|
589
|
+
查找顺序如下,第一条命中即用:
|
|
590
|
+
|
|
591
|
+
| 顺序 | 来源 | 说明 |
|
|
592
|
+
|---|---|---|
|
|
593
|
+
| 1 | `record_*(..., ffmpeg="路径")` | 显式指定,优先级最高 |
|
|
594
|
+
| 2 | 环境变量 `IMAGEIO_FFMPEG_EXE` | 与广泛使用的 `imageio-ffmpeg` 包同一约定 |
|
|
595
|
+
| 3 | **wheel 内自带的 ffmpeg** | 仅 `py3-none-win_amd64` wheel 有;开箱即用 |
|
|
596
|
+
| 4 | 已安装的 `imageio_ffmpeg` 包 | 装了它就不需要任何配置 |
|
|
597
|
+
| 5 | `PATH` 上的 `ffmpeg` | 系统级安装 |
|
|
598
|
+
|
|
599
|
+
其他环境(32 位 Windows、ARM64 原生 Python)拿到的是纯 Python 的 `py3-none-any` wheel,里面没有二进制。
|
|
600
|
+
这种情况下按需补一个即可:
|
|
601
|
+
|
|
602
|
+
```bash
|
|
603
|
+
pip install "VirtualDesktop[ffmpeg]" # 等价于装 imageio-ffmpeg(Windows x64 约 30 MB)
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
都没找到时,视频格式会**明确报错**(`code="ffmpeg-missing"`)并提示改用 `.gif` 或帧序列——不会静默产出坏文件。
|
|
607
|
+
|
|
608
|
+
#### 关于内嵌 ffmpeg 与许可证(重要)
|
|
609
|
+
|
|
610
|
+
`py3-none-win_amd64` wheel 里那份 ffmpeg 是 **GPLv3** 的,因为:
|
|
611
|
+
|
|
612
|
+
- 输出 **H.264 需要 `libx264`,而它是 GPL-only**。因此 Windows 上**能编 H.264 的 ffmpeg 构建基本都是 GPL**。
|
|
613
|
+
- 纯 **LGPL** 的 ffmpeg 构建**不含 libx264**,编不了 H.264(只有 mpeg4 / vp8 / vp9 之类)。
|
|
614
|
+
- 也就是说"内嵌 ffmpeg 且保持宽松许可"这两件事**无法同时满足**。选择了开箱即用,就接受了这份 GPL 二进制。
|
|
615
|
+
|
|
616
|
+
边界是清楚的:ffmpeg 是**独立进程**,本库通过管道喂帧、用 `subprocess` 启动它,二者是**聚合**而非链接关系;
|
|
617
|
+
**本库自身的 Python 代码始终是 MIT**。二进制旁边的 `VirtualDesktop/_vendor/FFMPEG-LICENSE.txt` 写明了来源、
|
|
618
|
+
版本、SHA-256 与许可证全文地址。
|
|
619
|
+
|
|
620
|
+
| 你的偏好 | 做法 |
|
|
621
|
+
|---|---|
|
|
622
|
+
| 开箱即用、可接受安装物含 GPL 组件 | 直接用 `py3-none-win_amd64` wheel(默认就是它) |
|
|
623
|
+
| 不想要 GPL 二进制落盘 | 先 `pip download VirtualDesktop==<版本> --no-deps` 拿到 `py3-none-any` 那份再本地安装;或装完删掉 `_vendor/ffmpeg.exe`——库会照常回退到上面第 4、5 条 |
|
|
624
|
+
| 保持 MIT/LGPL 干净 | 用 `.gif` / 帧序列,或自备 LGPL 版 ffmpeg 并改用 WebM(VP9) 等非 H.264 编码 |
|
|
625
|
+
| 完全不想装 | 用 `.gif`(画质与体积不如 MP4,但零依赖) |
|
|
626
|
+
|
|
627
|
+
> 无论哪种方式,本库自身的代码始终是 **MIT**,可自由用于闭源项目;GPL 义务只落在那份 ffmpeg 二进制上。
|
|
628
|
+
> 若你要把它**再分发**出去(而不只是自己用),需自行遵守其许可证:附许可证文本并提供源码获取方式。
|
|
629
|
+
|
|
552
630
|
> 内容完全相同的连续帧会被 GIF 优化合并成一个条目(延迟累加),所以 GIF 的**帧数可能少于
|
|
553
631
|
> 录制帧数**,但总时长不变。`report().frames` 报的是实际**采集**帧数。
|
|
554
632
|
|
|
@@ -676,7 +754,7 @@ VIRTUALDESKTOP_LOG_FILE=<path>
|
|
|
676
754
|
| 桌面截图拍不到工作区窗口 | 用了 `offscreen`,窗口在所有显示器之外 | 改用 `hide_mode="virtual_screen"` |
|
|
677
755
|
| `capture_desktop()` 报"workspace has no monitor" | `offscreen` 模式没有属于自己的屏幕区域 | 用 `hide_mode="virtual_screen"`,或改用 `capture(hwnd)` / `record_window(hwnd)` |
|
|
678
756
|
| 录制报 `record-would-capture-user-screen` | 工作区用的是物理屏 | 改用虚拟显示器;确实要录主屏请显式传 `monitor="primary"` |
|
|
679
|
-
| 录制报 `ffmpeg-missing` |
|
|
757
|
+
| 录制报 `ffmpeg-missing` | 目标格式是视频,但既没有自带二进制(非 x64 wheel),也没有可用的 ffmpeg | 装 `VirtualDesktop[ffmpeg]`、传 `ffmpeg=<路径>`,或改录 `.gif` / 帧序列 |
|
|
680
758
|
| 桌面截图/录制**所有**显示器都报 `desktop-capture-failed`,`BitBlt` 与 `GetPixel` 一起失效 | 桌面设备上下文的像素读取能力整体失效(显示栈状态异常,不是本库也不是驱动残留) | **注销重登或重启系统**即可恢复;窗口截图(`PrintWindow`)不受影响,可继续用 |
|
|
681
759
|
| 真实鼠标点击无效 | 窗口在屏幕之外,或拿不到前台焦点 | 用 `virtual_screen`,或改用消息驱动 |
|
|
682
760
|
|
|
@@ -760,4 +838,9 @@ set VIRTUALDESKTOP_GITHUB_MIRRORS=https://gh-proxy.com/,https://internal.example
|
|
|
760
838
|
|
|
761
839
|
# 许可证
|
|
762
840
|
|
|
763
|
-
MIT
|
|
841
|
+
本库自身的 Python 代码是 **MIT**,见 [LICENSE](LICENSE)。
|
|
842
|
+
|
|
843
|
+
`py3-none-win_amd64` wheel 内附的 `VirtualDesktop/_vendor/ffmpeg.exe` 是第三方程序,按 **GPLv3** 分发
|
|
844
|
+
(因为它带 `libx264`)。它与本库是**聚合**关系:独立进程、管道通信,不与 MIT 代码链接。来源、版本与
|
|
845
|
+
SHA-256 见 `VirtualDesktop/_vendor/FFMPEG-LICENSE.txt`。不需要它的话,装纯 Python wheel
|
|
846
|
+
(`py3-none-any`)即可,本库代码一字不改。
|