用途
FilmKit 是面向富士 X 系列相机的浏览器端、零安装预设管理器与 RAW 转换器。它通过 WebUSB 以 PTP(Picture Transfer Protocol,图片传输协议)与相机通信——与富士 X RAW STUDIO 使用相同协议,由相机自身的图像处理器完成 RAW 到 JPEG 的转换。整个应用完全在客户端运行(托管于 GitHub Pages),支持桌面端和 Android。
主要能力
- 预设管理:直接在相机上读取、编辑和写入自定义胶片模拟预设(插槽 D18E–D1A5,通过 PTP GetDevicePropValue / SetDevicePropValue)。
- 本地预设库:本地保存预设,可在相机与本地存储之间拖拽。
- RAW 转换与实时预览:将 RAF 文件发送至相机,取回全画质 JPEG。
- 预设检测:加载 RAF 文件时自动检测拍摄所用预设。
- 导入/导出:预设可作为文件、链接或文本粘贴方式导入导出。
- 移动端支持:通过 Chrome 的 WebUSB 支持在 Android 上使用。
使用方式
环境要求:桌面或 Android 上的 Chromium 系浏览器(Google Chrome、Edge、Brave)——必须支持 WebUSB;通过 USB 连接的富士 X 系列相机(已在 X100VI 测试;可能适用于 X-T5、X-H2、X-T30 等);若在 Flatpak 中运行 Chrome,需要 Linux udev 规则:
# /etc/udev/rules.d/99-fujifilm.rules
SUBSYSTEM=="usb", ATTR{idVendor}=="04cb", MODE="0666"
添加后重载规则:
sudo udevadm control --reload-rules && sudo udevadm trigger
本地安装/开发:FilmKit 是静态 TypeScript 应用。
git clone https://github.com/eggricesoy/filmkit.git
cd filmkit
npm install
npm run dev
生产构建:
npm run build
构建输出为静态站点,无需服务器。在 Chrome 中打开 http://localhost:5173(或 Vite 服务的地址)。
架构概览
基于 WebUSB 的 PTP:FilmKit 直接通过 USB 批量传输使用 PTP。关键操作包括:GetDevicePropValue(读取相机预设属性)、SetDevicePropValue(写入相机预设属性)、InitiateOpenCapture(开始 RAW 转换会话)、SendObject(将 RAF 文件发送至相机)、GetObject(从相机取回转换后的 JPEG)。
预设属性代码:富士 X 系列相机将胶片模拟参数暴露为 0xD18E–0xD1A5 范围内的设备属性,例如 FILM_SIMULATION 为 0xD18E、GRAIN_EFFECT 为 0xD18F、COLOR_CHROME 为 0xD190、WHITE_BALANCE 为 0xD191、COLOR_TEMP 为 0xD192、DYNAMIC_RANGE 为 0xD193、HIGHLIGHT_TONE 为 0xD194、SHADOW_TONE 为 0xD195、COLOR 为 0xD196、SHARPNESS 为 0xD197、HIGH_ISO_NR 为 0xD198(非线性编码!)、CLARITY 为 0xD199。
原生配置文件格式:相机原生 d185 配置文件为 625 字节,使用的字段索引/编码与 RAF 文件元数据不同。FilmKit 采用基于补丁的方式:逐字节复制基础配置文件,仅覆盖用户更改的字段,从而保留未更改字段中的 EXIF 哨兵值。
关键代码模式
- WebUSB 连接:通过 navigator.usb.requestDevice 请求访问,过滤器为 vendorId 0x04CB(富士厂商 ID),然后 open、selectConfiguration(1)、claimInterface(0)。
- 发送 PTP 命令:构建 12 字节加参数的命令包(长度、类型 0x0001、操作码、事务 ID、参数),通过批量端点 0x02 发送,从 0x81 读取响应。
- 读取预设属性:PTP 操作 0x1015(GetDevicePropValue),PTP 数据容器为 12 字节头部加负载。
- 写入预设属性:PTP 操作 0x1016(SetDevicePropValue),构建数据容器(类型 0x0002),按 1/2/4 字节大小写入值。
- HighIsoNR 特殊编码:使用非线性专有编码(经 Wireshark 逆向),用户值 -4 至 +4 分别映射为 0x00、0x01、0x02、0x03、0x04、0x08、0x0C、0x10、0x14。
- 条件写入(黑白胶片模拟):黑白胶片模拟会拒绝 Color 属性写入,需先判断是否属于黑白集合(ACROS、ACROS+Ye、ACROS+R、ACROS+G、Monochrome、Monochrome+Ye、Monochrome+R、Monochrome+G、Eterna Cinema BW)再决定是否写入 Color。
RAW 转换流程
- 将预设属性写入相机;2. 发起 InitiateOpenCapture(0x101C)会话;3. 发送 RAF 文件(SendObject,0x100D);4. 轮询并使用 GetObject(0x1009)取回 JPEG。
预设导入/导出格式
预设以结构化数据(JSON 或编码字符串)导出,字段包括 name、filmSimulation、grainEffect、colorChrome、whiteBalance、colorTemperature(仅当 WB 为色温模式 0x0012 时使用)、dynamicRange、highlightTone、shadowTone、color、sharpness、highIsoNR(面向用户的值 -4 至 +4,写入前需编码)、clarity。链接导出使用 base64 编码的 JSON,形如 https://filmkit.eggrice.soy/?preset=<encoded>。导入支持 URL 的 ?preset= 参数、原始 base64 或 JSON。
为新相机添加支持
- 安装带 USBPcap 的 Wireshark;2. 捕获 USB 总线(USBPcap1),过滤 usb.transfer_type == 0x02(批量传输即 PTP 流量);3. 在 X RAW STUDIO 中执行:配置文件读取、预设保存(更改所有预设值并保存到插槽)、RAW 转换(加载 RAF 并用预设转换);4. 保存每段捕获为 .pcapng;5. 提交 GitHub issue,附相机型号、固件版本、全部三个 .pcapng 文件及所用参数值。
故障排查
- WebUSB 不可用:必须使用 Chrome 或 Chromium 系浏览器(Firefox 不支持 WebUSB);Android 上使用 Chrome;检查 chrome://flags 确保未启用 "Disable WebUSB"。
- 相机未被检测到:确保相机处于 USB 模式(MTP 或 PTP,而非大容量存储);Linux 非 Flatpak 下检查用户是否在 plugdev 组;Linux Flatpak Chrome 下为厂商 04cb 添加 udev 规则并重载。
- Linux 权限被拒:用 lsusb 检查富士设备并验证 /dev/bus/usb 下设备权限。
- PTP 事务错误:确保没有其他应用(X RAW STUDIO、Capture One 等)同时连接相机;同一时间只能有一个 WebUSB 消费者持有接口;若接口卡住,断开并重新连接相机。
- 预设写入被拒:在黑白胶片模拟上写入 Color 属性会被拒绝,属预期行为;写入色温需先将 WB 模式设为 0x0012;HighIsoNR 必须使用非线性编码值。
- 调试日志:在 FilmKit UI 右侧边栏底部滚动到 Debug 部分,点击 Copy Log,粘贴到 GitHub issue 中报告问题。
适用场景与限制
适用于富士 X 系列相机用户通过浏览器管理胶片模拟预设与转换 RAW 文件,尤其方便在 Android 移动设备上操作,且无需安装原生软件。限制方面:仅支持 Chromium 系浏览器,依赖 WebUSB;需通过 USB 连接相机;已在 X100VI 测试,其他型号可能兼容但暂未提供完整验证;黑白胶片模拟下无法写入 Color 属性;色温与 HighIsoNR 有特定写入顺序与编码要求;同一时间相机接口只能由一个 WebUSB 消费者持有。官方未提供收费、价格等信息,暂未提供。
关键链接
- 在线应用:https://filmkit.eggrice.soy
- 协议参考:QUICK_REFERENCE.md
- 相关项目:rawji、fudge、libgphoto2
- Fuji X Weekly 预设:https://fujixweekly.com/