Files
pyheic_struct/docs/README.md
T
2025-10-23 18:12:08 +13:00

182 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`
---
## 快速开始:把三星动态照片变成 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,特别是其它安卓厂商的兼容性案例。