iochan-ship-it/fp-l-tether
GitHub: iochan-ship-it/fp-l-tether
一个专为Sigma fp L相机在macOS上实现联机拍摄的开源工具,解决摄影棚工作中的实时控制和自动化工作流问题。
Stars: 0 | Forks: 0
# sequence, it should be in Chinese? No, the rule says to keep professional terms in English, so I'll output "fp-l-tether" in English.
[]()
[]()
[](LICENSE)
[]()
## 功能介绍
`fp-l-tether` 是一个专为 macOS 上的 Sigma fp L 设计的独立联机拍摄守护进程和浮动控制面板。其主要特性包括:
- **实时视图**,帧率最高可达 10 fps,支持点击对焦
- **可分离的实时视图窗口** (⌘D) — 可将实时视图从面板中弹出,调整为可缩放的 3:2 窗口,适用于艺术品复制/摄影棚工作
- **RGB 直方图叠加显示** (H / ⌘H),在实时视图上显示高光/阴影溢出标记
- **构图网格叠加显示** (G / ⌘G) — 可在三分法/黄金比例/10×6 对齐网格间循环切换
- **浮动控制面板**,可跟随您在不同 macOS 桌面空间和 Lightroom 全屏模式间移动
- **Lightroom Classic 自动导入**集成 — 每次拍摄的照片都会自动进入您的目录
- **自动 USB 恢复** — 当 fp L 的批量端点挂起时(一个已知的固件特性),此守护进程会检测到该问题,并在约 4 秒内通过 IOKit 强制重新枚举设备。无需物理断电重启。
- **持久化设置缓存** — 您的 ISO / SS / 光圈 / 白平衡 / 格式以及实时视图窗口状态会在断开连接和恢复后被记住
- **JPG / DNG / DNG+JPG** 拍摄及双文件提取
- **曝光控制** — ISO、快门速度、光圈、白平衡、格式、分辨率,均可通过浮动面板下拉菜单调整
- **质实刚健 UI** — 阳极氧化黑 + 琥珀色点缀 + SF Mono 主要数值,灵感源自 Sigma fp 的工业设计
状态:功能完整,作者每日用于摄影棚产品摄影。非常欢迎错误报告和拉取请求。
## 截图展示
### 浮动控制面板

紧凑的面板位于 Lightroom Classic 之上,并可跨 macOS 桌面空间使用。
顶部是带有点击对焦准星和 RGB 直方图条的实时视图(角落显示高光/阴影溢出百分比)。
主要曝光数值(ISO、快门、光圈)使用 SF Mono 字体显示,另有用于格式、分辨率和白平衡的下拉菜单。空格键拍摄;`A` 键对焦;`H`/`G` 键切换叠加显示。
### 可分离的实时视图窗口

`⌘D` 可将实时视图弹出为可缩放的 3:2 窗口,适用于艺术品复制/摄影棚工作。
点击对焦、RGB 直方图和构图网格在分离窗口中均保持有效。
紧凑面板会缩小,仅显示曝光控制,并用一个清晰的占位符表明实时视图已分离。
## 项目初衷
Sigma fp L 是一款卓越的小型相机,值得拥有出色的联机拍摄体验。这是一个面向摄影爱好者的社区构建选项,特别是那些希望 fp L 拍摄的照片能直接进入 Lightroom Classic 并享受工具定制过程的用户。
## 快速上手
### 安装
```
git clone https://github.com/iochan-ship-it/fp-l-tether.git
cd fp-l-tether
python3 -m venv venv
source venv/bin/activate
pip install -e .
```
### 连接相机
1. 将 fp L 电源**关闭**
2. CINE/STILL 开关切换至 **STILL**
3. **打开**电源
4. MENU → 系统 → **USB 模式 → 相机控制**
5. 关闭电源,将 USB-C 线接入 Mac,然后**打开**电源
### 运行
```
# Now, line 2: "Kill macOS's built-in PTP daemon first (claims the camera exclusively)."
sudo killall ptpcamerad
# - "Kill" is a verb, which can be translated to Chinese.
sudo venv/bin/fp-l-tether start
```
需要 `sudo` 是因为 libusb 必须从相机的 PTP 接口卸载内核驱动程序。有关权限模型的解释,请参阅 `docs/SETUP.md`。
### Lightroom 集成
守护进程会将每张拍摄的照片原子性地写入一个监视文件夹。将 Lightroom Classic 的 **文件 → 自动导入 → 自动导入设置...** 指向该文件夹,您的照片在保存后就会自动出现在目录中。完整设置说明请参阅 `docs/LIGHTROOM.md`。
## 功能状态
| 功能 | 状态 |
|---|---|
| 拍摄(单张,PC 触发) | ✅ 可用 |
| 拍摄(相机按钮触发) | ✅ 可用 |
| 实时视图 (10 fps) | ✅ 可用 |
| 实时视图点击对焦 | ✅ 可用 |
| ISO / 快门 / 光圈 / 白平衡 / 格式 / 分辨率控制 | ✅ 可用 |
| Lightroom 自动导入 | ✅ 可用 |
| USB 挂起自动恢复 | ✅ 可用(约 4 秒) |
| 断开后重连的设置保留 | ✅ 可用 |
| 连拍 / 连续拍摄 | ⚠️ 仅单张模式 (mode=2)。连续拍摄已在计划中。 |
| 视频/影片联机 | ❌ 不支持,无计划 |
| Linux / Windows | ❌ 仅限 macOS(恢复路径依赖 IOKit) |
## 项目结构
```
fp_l_tether/ # Python package
camera/
ptp_codes.py # PTP opcodes + dataclasses + wire parsers
usb_bridge.py # libusb PTP transport + capture/download
sigma_datagroup.py # DataGroup IFD parser + exposure decode
usb_recovery.py # IOKit USBDeviceReEnumerate driver
settings_preservation.py # Snapshot/restore user-dialed settings
ic_bridge.py # ImageCaptureCore enumeration (limited)
transfer/
watcher.py # TetherDaemon main loop
liveview.py # Live View stream
heartbeat.py # USB keep-alive
atomic.py # Atomic write helper
lightroom/
destinations.py # Watch folder / session folder router
ui/
cli.py # Typer CLI (start / shoot / status / inspect)
floating_panel.py # PyObjC NSPanel with LV + AF overlay
storage/
settings_cache.py # Persistent settings cache
telemetry/
logger.py # structlog wrappers
config/
__init__.py # Pydantic-validated TOML config
scripts/ # Diagnostic & verification scripts
phase3_usb_reenum_test.py # Standalone USB recovery verifier
phase3_liveview_*.py # Live View diagnostics
docs/
SETUP.md # macOS setup, libusb, ptpcamerad notes
LIGHTROOM.md # Lightroom Classic Auto Import setup
TROUBLESHOOTING.md # Common issues
tests/unit/ # pytest tests (no camera needed)
config.example.toml # Example config; copy to config.toml to override defaults
```
## 系统要求
- macOS 12 (Monterey) 或更高版本(已在 macOS 26 Apple Silicon 上测试)
- Python 3.10+
- [Homebrew](https://brew.sh) + `libusb`:`brew install libusb`
(或依赖捆绑的 `libusb-package` wheel)
- Sigma fp L 处于**相机控制** USB 模式
- USB-C 线缆,直接连接 Mac(避免使用集线器)
- 需要 `sudo` 权限以卸载 libusb 内核驱动
- Adobe Lightroom Classic(可选,用于自动导入工作流)
## 工作原理(高级概述)
该守护进程运行三个协调线程,共享一个 libusb 批量端点:
1. **主循环** — 轮询 `GetCaptureStatus(slot=N)`,其中 `N` 是相机的 `image_db_head`,处理拍摄/对焦/曝光请求队列,并通过 `GetBigPartialPictFile` 下载已完成的照片。
2. **实时视图线程** — 以 10 fps 的帧率通过 `GetCamViewFrame` (0x902b) 抓取 JPEG 预览帧,在拍摄/对焦期间暂停,并对 `0x2019 DeviceBusy` 风暴拥有独立的指数退避机制。
3. **心跳线程** — 每 30 秒发送一个无害的保活操作码(默认:`sigma_get_camera_info`)。
当任何线程检测到 fp L 的批量端点挂起(`Errno 60` / 0 字节读取 — 一个已知的固件休眠特性)时,主循环会拆除会话并通过 IOKit 调用 `IOUSBDeviceInterface::USBDeviceReEnumerate()`,这会强制 macOS USB 主控制器断开并重新枚举该设备。
效果等同于物理拔插线缆,但由软件驱动。新的连接桥会建立,持久化设置缓存会重放回相机,实时视图在约 4 秒内恢复。
设置保留的工作原理类似:在每次(重新)连接时,守护进程会从 `~/.fp-l-tether/user_settings.json` 读取用户最后使用的有效值,并通过每项对应的 `SetCamDataGroup1/2` 操作码将其写入 DG1 和 DG2。
当用户通过浮动面板更改设置时,缓存会随之更新。
完整的状态机逻辑请参见 `fp_l_tether/transfer/watcher.py`。
## 许可证
本项目根据 [MIT 许可证](LICENSE) 发布。
第三方归属信息请见 `NOTICE` 文件。
“SIGMA”、“Sigma fp” 和 “Sigma fp L” 是 SIGMA 公司的商标。
本项目**与 SIGMA 公司无关联、未获其认可或赞助**。
此处记录的 PTP 线格式细节是通过对 Sigma fp L 的公共 USB 流量进行“净室”观察获得的,符合美国法典第 17 卷第 1201(f) 条的互操作性条款以及欧盟指令 2009/24/EC 第 6 条。
标签:Beta 版本, DNS解析, IOKit 框架, Lightroom 集成, macOS 软件, Python 开发, RGB 直方图, Sigma fp L, USB 恢复, USB 设备管理, 双文件提取, 实时视图, 工业设计, 工作室摄影, 开源项目, 持久化设置, 摄影工作流, 摄影工具, 摄影软件, 效率工具, 曝光控制, 构图网格, 浮动控制面板, 相机控制, 系留拍摄, 自动导入, 自动恢复, 艺术复制品, 设备枚举, 软件开发, 逆向工具