# pyheic-struct `pyheic-struct` 诞生的初衷,是为了解决我个人在迁移照片时遇到的需求:把三星手机拍摄的动态照片(Motion Photo)批量转换成 iOS/macOS 可以直接识别、导入的 Live Photo。 工具会自动拆分并重建 HEIC 与 MOV 配对文件,补齐 Apple 生态所必需的 `ContentIdentifier`、`PhotoIdentifier` 与 MakerNote 元数据,让 macOS「照片」或 iOS 设备将它们视为同一张 Live Photo,而不是互不关联的静态图与视频。 > Looking for an English version? Please see [README.en.md](README.en.md). *(本 README 以中文为主,当需要英文说明时可跳转到该文件。)* 同时,转换流程也促使我编写了一套可复用的 HEIF/HEIC 结构化解析、诊断与重建工具:它能读出盒结构、修复三星特有的 shifted item ID、重算 `iloc` 偏移,并以可预测的方式重新写回文件。即便你暂时不需要完整的 Live Photo 转换,也能够将其中的模块用在其它 HEIC 调试或自定义处理流程中。 --- ## 功能亮点 - **三星 Motion Photo → Apple Live Photo**:自动生成匹配的 HEIC 与 MOV,并写入统一的标识符;导入后即是一张可播放的 Live Photo。 - **完整元数据补齐**:在 MOV 中注入 `ContentIdentifier`,在 HEIC 中写入 MakerNote / PhotoIdentifier 等 Apple 生态所需字段。 - **HEIC 深层解析能力**:提供 `HEICFile`、`HEICBuilder` 等类,可读取 `ftyp`、`meta`、`iloc`、`iinf`、`iprp`、`iref` 等关键盒,适用于诊断和自定义修复。 - **安全重建机制**:`HEICBuilder` 会自动重算偏移量与引用关系,避免手工编辑造成的结构损坏。 - **CLI 与 Python API 并存**:既能在命令行一键转换,也可以在脚本、流水线甚至 GUI 中复用底层逻辑。 - **真实样例随仓库提供**:包含原始三星 HEIC、转换后的 Apple 兼容文件与苹果原生样例,便于对照调试。 --- ## 组件概览 | 组件 | 作用 | | --- | --- | | `scripts/samsung_to_live_photo.py` | 命令行转换脚本,输出苹果兼容的 HEIC + MOV | | `scripts/batch_media_manager.py` | 图形化批处理工具:扫描目录、转换 Motion Photo、匹配 Live Photo 配对、清理由 MotionPhoto_Data 标记的冗余视频,并可归档原始素材 | | `pyheic_struct.HEICFile` | 解析 HEIC 盒结构、重建主图、提取 Motion Photo 等 | | `pyheic_struct.HEICBuilder` | 在修改元数据后重新写出 HEIC,确保偏移正确 | | `pyheic_struct.convert_motion_photo` | 通用转换入口,可指定厂商与目标适配器 | | `pyheic_struct.AppleTargetAdapter` | Apple 生态适配器,负责写入品牌、MakerNote、ContentIdentifier 等 | | `pyheic_struct.handlers.SamsungHandler` | 三星专用处理逻辑:识别 `mpvd`、校正 shifted IDs | | `inspect_heic.py` | 快速巡检脚本,输出盒结构、偏移与引用信息 | --- ## 安装与环境 - **Python 3.10+** - 必装依赖:`Pillow>=10.0.0`、`pillow-heif>=0.15.0` - 新增依赖:`piexif>=1.1.3`(用于 MakerNote 写入) - 可选依赖:`exiftool-wrapper>=0.5.0` - 推荐系统安装 [ExifTool](https://exiftool.org/) - macOS: `brew install exiftool` - Ubuntu/Debian: `sudo apt install libimage-exiftool-perl` - Windows: 下载官方 exe 并加入 `PATH` 安装方式: ```bash # 仓库根目录安装 pip install . # 或开发模式(含可选依赖) pip install -e .[full] ``` 如仅需解析能力,可忽略 `.[full]`;若要写入 MOV 的 `ContentIdentifier`,请启用 `full` 并确保系统可调用 `exiftool`。 --- ### Windows/macOS 一键可执行程序 如果希望直接在 Windows 或 macOS 上使用单独的可执行文件,可以: - 在 GitHub Actions 中运行 **Build Samsung Live Photo binaries** 工作流(或等待自动触发),在构建完成后下载 `SamsungToLivePhoto-windows` / `SamsungToLivePhoto-macos` 构件; - 解压后按照压缩包内的 `README.txt` 操作即可(文件位于仓库的 `packaging/README_windows.txt` 与 `packaging/README_macos.txt`)。 若想自行本地打包,可在目标系统直接执行: ```bash # Windows (PowerShell) python -m pip install ".[full]" pyinstaller pyinstaller --noconfirm --onefile --name SamsungToLivePhoto ` --collect-all pillow_heif --collect-all pyheic_struct ` scripts/samsung_to_live_photo.py # macOS (bash/zsh) python3 -m pip install ".[full]" pyinstaller pyinstaller --noconfirm --onefile --name SamsungToLivePhoto \ --collect-all pillow_heif --collect-all pyheic_struct \ scripts/samsung_to_live_photo.py ``` 打包完成后,可执行文件会出现在 `dist/` 目录。Windows 版本为 `SamsungToLivePhoto.exe`,macOS 版本为 `SamsungToLivePhoto`。 --- ## 快速开始:把三星动态照片变成 Live Photo ### 1. 准备样例 仓库中已经附带常用测试素材(位于 `examples/` 目录): - `examples/samsung.heic`:原始三星 Motion Photo - `examples/samsung_apple_compatible.HEIC` / `.MOV`:转换后的示例输出 - `examples/apple.HEIC`:来自苹果的原生 Live Photo 参考 ### 2. 命令行一键转换 ```bash python3 scripts/samsung_to_live_photo.py examples/samsung.heic \ --output-dir output/live ``` 生成的 `output/live/samsung_apple_compatible.heic` 与 `.mov` 拥有同一个 `ContentIdentifier` 和 `PhotoIdentifier`,可直接导入 macOS「照片」验证。 常用参数: | 参数 | 说明 | | ---- | ---- | | `source` | 必选,原始三星 HEIC | | `--output-dir` | 输出目录,默认与源文件相同路径 | | `--heic-name` / `--mov-name` | 输出文件名(不含路径),默认 `*_apple_compatible` | | `--skip-mov-tag` | 无 `exiftool` 时跳过 MOV 的 `ContentIdentifier` 注入 | ### 3. 通过 API 集成 ```python from pathlib import Path from pyheic_struct import convert_samsung_motion_photo, HEICFile, HEICBuilder heic_path, mov_path = convert_samsung_motion_photo( "examples/samsung.heic", output_still=Path("converted/apple_ready.HEIC"), output_video=Path("converted/apple_ready.MOV"), ) # 读取重建后的 HEIC,执行进一步操作 rebuilt = HEICFile(str(heic_path)) rebuilt.set_content_identifier("MY-INTERNAL-ID") HEICBuilder(rebuilt).write("converted/customized.HEIC") ``` --- ### 4. 图形化批处理工具(GUI) `scripts/batch_media_manager.py` 提供完整的桌面界面,便于批量巡检目录: - 递归扫描 HEIC/MOV/MP4 等媒体,并以进度条与日志反馈处理情况; - 检测 Live Photo 配对,自动移动缺失伴侣的孤立视频到安全子目录; - 将三星 Motion Photo 转换为 Apple 兼容的 HEIC + MOV,并补写 `ContentIdentifier`; - 清理带 `MotionPhoto_Data` 标签、与 Motion Photo 重复的冗余 MP4; - 可选地把成功转换的原始素材按照原路径层级移动到 `归档/`(或 `Archive/`)并打包 zip; - 内置“停止”按钮和窗口关闭钩子,可安全取消长时间任务。 运行示例: ```bash python3 scripts/batch_media_manager.py ``` --- ## Live Photo 转换管线解读 1. **解析原始 HEIC**:读取 `ftyp`、`meta`、`iloc` 等盒;通过 handler 自动识别三星文件并查找 `mpvd` 盒。 2. **重建主图像**:借助 `pillow-heif` 还原三星的网格化主图,写入临时平面 HEIC(`mif1` brand)。 3. **提取并存储 MOV**:抽取 `mpvd` 中的嵌入视频,写成独立 MOV,并用 `exiftool` 写入 `ContentIdentifier`(如未安装可跳过)。 4. **修正 item ID 与引用**:三星会将 item ID 左移 16 位;工具会同步修复 `iinf`、`ipma`、`iref`。 5. **补齐 Apple 元数据**:设置苹果兼容的 `ftyp` 品牌,写入新的 `ContentIdentifier`、`PhotoIdentifier`,填充 MakerNote。 6. **最终重建**:`HEICBuilder` 重新计算 `iloc` 偏移、盒大小并写回,释放临时文件。 了解以上步骤,有助于调试其它厂商的 Motion Photo,或在需要时定制新的 TargetAdapter。 --- ## 核心 API 快速索引 - `pyheic_struct.convert_motion_photo(...)`:通用转换接口,可指定 `vendor_hint`(如 `"samsung"`)与 `TargetAdapter`。 - `pyheic_struct.convert_samsung_motion_photo(...)`:三星专用封装,调用更简洁。 - `pyheic_struct.HEICFile`: - `get_primary_item_id()`、`reconstruct_primary_image()`、`list_items()` 等解析方法 - `set_content_identifier()`、`set_exif_maker_note()` 等元数据操作 - `pyheic_struct.HEICBuilder`:将修改后的 `HEICFile` 安全写回磁盘。 - `pyheic_struct.handlers.VendorHandler`:厂商自定义扩展基类。 - `pyheic_struct.targets.TargetAdapter` / `AppleTargetAdapter`:目标生态适配接口。 --- ## 扩展与自定义 1. **实现新的厂商 Handler**:继承 `VendorHandler`,实现 `matches`、`extract_motion_video`、`prepare_flat_heic` 等方法,并注册到 `HANDLER_REGISTRY`。 2. **接入其它目标生态**:继承 `TargetAdapter`,在 `apply_to_flat_heic` / `post_process_mov` 中写入所需元数据或外部脚本。 3. **诊断 HEIC 文件**:使用 `inspect_heic.py` 或直接调 `HEICFile` API,输出盒结构、偏移与引用,便于对比不同厂商实现。 --- ## 常见问题 - **导入照片后仍显示两个文件?** 请确认系统安装了 `exiftool`,并在转换时未使用 `--skip-mov-tag`。同时建议使用工具生成的最新 HEIC/MOV,避免手动修改导致标识符不匹配。 - **能否支持其它厂商的 Motion Photo?** 可以。通过实现新的 handler 并组合自定义 target adapter,即可重用现有的重建管线。 - **英文说明在哪里?** 参见 [README.en.md](README.en.md);若你想贡献改进英文文档,也欢迎提交 PR。 --- ## 开发提示 - 项目使用 `ruff` / `black` 风格指南,可根据需要自行配置。 - 在修改 HEIC 结构后务必重新运行转换脚本,确保 `HEICBuilder` 输出的文件能被 `pillow-heif` 与 `exiftool` 读取。 - 欢迎围绕 HEIC 解析、Motion Photo 适配提交 issue 或 PR,特别是其它安卓厂商的兼容性案例。