8.7 KiB
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 以中文为主,当需要英文说明时可跳转到该文件。)
同时,转换流程也促使我编写了一套可复用的 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_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
- macOS:
brew install exiftool - Ubuntu/Debian:
sudo apt install libimage-exiftool-perl - Windows: 下载官方 exe 并加入
PATH
- macOS:
安装方式:
# 仓库根目录安装
pip install .
# 或开发模式(含可选依赖)
pip install -e .[full]
如仅需解析能力,可忽略 .[full];若要写入 MOV 的 ContentIdentifier,请启用 full 并确保系统可调用 exiftool。
快速开始:把三星动态照片变成 Live Photo
1. 准备样例
仓库中已经附带常用测试素材:
samsung.heic:原始三星 Motion Photosamsung_apple_compatible.HEIC/.MOV:转换后的示例输出apple.HEIC:来自苹果的原生 Live Photo 参考
2. 命令行一键转换
python3 scripts/samsung_live_photo.py 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 集成
from pathlib import Path
from pyheic_struct import convert_samsung_motion_photo, HEICFile, HEICBuilder
heic_path, mov_path = convert_samsung_motion_photo(
"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; - 内置“停止”按钮和窗口关闭钩子,可安全取消长时间任务。
运行示例:
python3 scripts/batch_media_manager.py
Live Photo 转换管线解读
- 解析原始 HEIC:读取
ftyp、meta、iloc等盒;通过 handler 自动识别三星文件并查找mpvd盒。 - 重建主图像:借助
pillow-heif还原三星的网格化主图,写入临时平面 HEIC(mif1brand)。 - 提取并存储 MOV:抽取
mpvd中的嵌入视频,写成独立 MOV,并用exiftool写入ContentIdentifier(如未安装可跳过)。 - 修正 item ID 与引用:三星会将 item ID 左移 16 位;工具会同步修复
iinf、ipma、iref。 - 补齐 Apple 元数据:设置苹果兼容的
ftyp品牌,写入新的ContentIdentifier、PhotoIdentifier,填充 MakerNote。 - 最终重建:
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:目标生态适配接口。
扩展与自定义
- 实现新的厂商 Handler:继承
VendorHandler,实现matches、extract_motion_video、prepare_flat_heic等方法,并注册到HANDLER_REGISTRY。 - 接入其它目标生态:继承
TargetAdapter,在apply_to_flat_heic/post_process_mov中写入所需元数据或外部脚本。 - 诊断 HEIC 文件:使用
inspect_heic.py或直接调HEICFileAPI,输出盒结构、偏移与引用,便于对比不同厂商实现。
常见问题
-
导入照片后仍显示两个文件?
请确认系统安装了exiftool,并在转换时未使用--skip-mov-tag。同时建议使用工具生成的最新 HEIC/MOV,避免手动修改导致标识符不匹配。 -
能否支持其它厂商的 Motion Photo?
可以。通过实现新的 handler 并组合自定义 target adapter,即可重用现有的重建管线。 -
英文说明在哪里?
参见 README.en.md;若你想贡献改进英文文档,也欢迎提交 PR。
开发提示
- 项目使用
ruff/black风格指南,可根据需要自行配置。 - 在修改 HEIC 结构后务必重新运行转换脚本,确保
HEICBuilder输出的文件能被pillow-heif与exiftool读取。 - 欢迎围绕 HEIC 解析、Motion Photo 适配提交 issue 或 PR,特别是其它安卓厂商的兼容性案例。