整理文件夹结构
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
# pyheic-struct (English Overview)
|
||||
|
||||
`pyheic-struct` exists because I needed a reliable way to convert Samsung Motion Photos into Apple-compatible Live Photos.
|
||||
It automatically produces a paired HEIC + MOV set, synchronises their `ContentIdentifier` / `PhotoIdentifier`, injects the required MakerNote fields, and makes macOS Photos or iOS treat them as a single Live Photo instead of two independent files.
|
||||
|
||||
The conversion pipeline is powered by a set of reusable tools for inspecting, editing, and rebuilding HEIF/HEIC containers. Even if you only need low-level diagnostics, you can reuse the parsing classes, the safety-first `HEICBuilder`, or the vendor/target adapter hooks.
|
||||
|
||||
---
|
||||
|
||||
## Highlights
|
||||
|
||||
- **Samsung Motion Photo → Live Photo**: export aligned HEIC and MOV files with matching identifiers.
|
||||
- **Metadata completion**: write Apple-specific MakerNote fields (`ContentIdentifier`, `PhotoIdentifier`, etc.).
|
||||
- **Deep HEIC inspection**: `HEICFile` exposes `ftyp`, `meta`, `iloc`, `iinf`, `iprp`, and references for debugging.
|
||||
- **Safe rebuild pipeline**: `HEICBuilder` recalculates offsets and references to avoid corrupted files.
|
||||
- **CLI + Python API**: run a one-shot conversion script or integrate with your own workflow.
|
||||
- **Sample assets included**: compare the supplied Samsung source, converted outputs, and Apple originals.
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
Requirements:
|
||||
|
||||
- Python 3.10+
|
||||
- Dependencies: `Pillow>=10.0.0`, `pillow-heif>=0.15.0`, `piexif>=1.1.3`
|
||||
- Optional: `exiftool-wrapper>=0.5.0`
|
||||
- Recommended: system-level [ExifTool](https://exiftool.org/) (needed for MOV tagging)
|
||||
|
||||
Install from source:
|
||||
|
||||
```bash
|
||||
pip install .
|
||||
# or, with extras for development + exiftool-wrapper
|
||||
pip install -e .[full]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
### CLI conversion
|
||||
|
||||
```bash
|
||||
python3 scripts/samsung_to_live_photo.py examples/samsung.heic --output-dir output/live
|
||||
```
|
||||
|
||||
The command writes `samsung_apple_compatible.heic` and `samsung_apple_compatible.mov` with the same UUIDs.
|
||||
|
||||
Key options:
|
||||
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| `--output-dir` | Target directory (defaults to the source directory) |
|
||||
| `--heic-name` / `--mov-name` | Custom output filenames |
|
||||
| `--skip-mov-tag` | Skip MOV `ContentIdentifier` injection when exiftool is unavailable |
|
||||
|
||||
### Python 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"),
|
||||
)
|
||||
|
||||
rebuilt = HEICFile(str(heic_path))
|
||||
rebuilt.set_content_identifier("MY-INTERNAL-ID")
|
||||
HEICBuilder(rebuilt).write("converted/customized.HEIC")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## How the pipeline works
|
||||
|
||||
1. **Parse the original HEIC** and detect Samsung-specific structures (`mpvd`, shifted item IDs).
|
||||
2. **Reconstruct the primary image** via `pillow-heif` and save a flat temporary HEIC.
|
||||
3. **Extract the embedded video**, save it as MOV, and (optionally) add `ContentIdentifier` using exiftool.
|
||||
4. **Fix shifted IDs and references** across `iinf`, `ipma`, and `iref`.
|
||||
5. **Inject Apple metadata**: set the brand tuple, write MakerNote, `ContentIdentifier`, and `PhotoIdentifier`.
|
||||
6. **Rebuild the file** with `HEICBuilder`, which recalculates offsets and cleans up temporary files.
|
||||
|
||||
---
|
||||
|
||||
## Key API reference
|
||||
|
||||
- `pyheic_struct.convert_motion_photo(...)`
|
||||
- `pyheic_struct.convert_samsung_motion_photo(...)`
|
||||
- `pyheic_struct.HEICFile`: parsing helpers, metadata mutators.
|
||||
- `pyheic_struct.HEICBuilder`: safe writer after modifications.
|
||||
- `pyheic_struct.handlers.VendorHandler`: extend for other Motion Photo vendors.
|
||||
- `pyheic_struct.targets.AppleTargetAdapter`: writes Apple-specific metadata.
|
||||
|
||||
---
|
||||
|
||||
## Need more?
|
||||
|
||||
The Chinese README (default) contains additional background, step-by-step guides, and FAQ:
|
||||
[返回中文文档 / Back to Chinese](README.md)
|
||||
+181
@@ -0,0 +1,181 @@
|
||||
# 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,特别是其它安卓厂商的兼容性案例。
|
||||
Reference in New Issue
Block a user