背景:
之前使用的iPhone 15 Pro,使用的Windows資源管理器當中復制導出的實況照片,復制出來的格式例如IMG_0001.JPG, IMG_0001.MOV。之后手機就賣掉了。現在使用的iPhone 14 Pro Max,想要導回之前備份的實況照片。嘗試使用愛思助手導入,雖然文件名都一樣,但是仍然會報錯:
是不是非常可惡?
但是使用愛思助手導出實況照片、出來的也是JPG+MOV。再重新導回去,發現一切正常。這么說一定是可以導入的,肯定是哪里出了問題。
咨詢了愛思助手的客服,完全不理。沒辦法,只好自己研究咯。
解決方法:
讀取MOV的EXIF信息
exiftool -a -u -g1 IMG_4676.MOV > IMG_4676.MOV.TXT
---- Keys ----字段下面的Content Identifier鍵值,就是JPG需要被修改成的Media Group UUID。也就是說,實際上,他們是依據這個uuid來判斷視頻和照片的關聯。發現愛思助手導出的JPG和MOV正好也是對應的。所以實際上,針對資源管理器復制出來的,我們只要讀取MOV的這個鍵值,把我們從JPG當中的Media Group UUID修改成一樣的即可!
# MOV
Content Identifier : E2523D1E-7C8A-423B-A8DB-53C8A073457F# JPG
Media Group UUID : E2523D1E-7C8A-423B-A8DB-53C8A073457F
修改JPG當中的Media Group UUID
利用010Editor,打開文件,
直接把我原始照片里面的UUID替換掉。保存,即可導入成功。
這個UUID在文件中是明文TEXT存儲的,在批量處理的情況下我們可以直接寫一個腳本,利用exiftool讀取出來MOV文件的Content Identifier,讀取JPG的Media Group UUID,然后字節流模式打開JPG,在文件當中直接執行替換即可。
批量處理代碼
Windows平臺,下載exiftool:
https://exiftool.org/index.html
?
下載這個stand-alone的windows版本 。
下載下來的zip里面就是一個exe文件,重命名為exiftool.exe即可。
創建下面的python文件,把exe和這個python文件放到一個目錄下面。
這個代碼會將成對的JPG+MOV都拷貝到一個新的文件夾里面去。這樣在原始文件夾里面的文件都是需要單獨導入成靜態照片和普通視頻的。方便導入。在愛思助手里面就直接選擇程序生成的LivePhoto文件夾。
建議在運行此代碼之前,把資料先備份一份,以防萬一。畢竟數據無價,謹慎操作。
import subprocess
import os
import shutil
from collections import defaultdict
import redef get_exif_data(file_path):try:process = subprocess.Popen(['exiftool', '-a', '-u', '-g1', file_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)stdout, stderr = process.communicate()if process.returncode != 0:print(f"Error: {stderr.strip()}")return Nonereturn stdout.strip()except FileNotFoundError:print("ExifTool is not installed or not found in the system path.")return Nonedef replace_uuid_in_jpg(jpg_file_path, old_uuid, new_uuid):with open(jpg_file_path, 'rb+') as jpg_file:file_content = jpg_file.read()updated_content = file_content.replace(old_uuid, new_uuid)jpg_file.seek(0)jpg_file.write(updated_content)jpg_file.truncate()def fix_jpg_for_ios_import(jpg_file_path, mov_file_path):exif_data = get_exif_data(mov_file_path).split(b'\n')content_identifier = Nonefor item in exif_data:if b'Content Identifier' in item:content_identifier = item.split(b':')[-1].strip()breakassert content_identifier is not Noneassert re.match(r'[0-9A-F]{8}(-[0-9A-F]{4}){3}-[0-9A-F]{12}', content_identifier.decode().upper())print(b' ' + mov_file_path.encode() + b' | ' + content_identifier)exif_data = get_exif_data(jpg_file_path).split(b'\n')media_group_uuid = Nonefor item in exif_data:if b'Media Group UUID' in item or b'Content Identifier' in item:media_group_uuid = item.split(b':')[-1].strip()breakassert media_group_uuid is not Noneassert re.match(r'[0-9A-F]{8}(-[0-9A-F]{4}){3}-[0-9A-F]{12}', media_group_uuid.decode().upper())print(b' ' + jpg_file_path.encode() + b' | ' + media_group_uuid)replace_uuid_in_jpg(jpg_file_path, media_group_uuid, content_identifier)def get_matching_files(directory):# 字典用于存儲文件名前綴及其對應的后綴file_dict = defaultdict(set)for filename in os.listdir(directory):name, ext = os.path.splitext(filename)ext = ext.upper()# 只處理JPG和MOV文件if ext in {'.JPG', '.MOV'}:file_dict[name].add(ext)# 找到同時具有JPG和MOV后綴的文件名前綴matching_files = [name for name, exts in file_dict.items() if {'.JPG', '.MOV'} <= exts]return matching_filesif __name__ == '__main__':jpg_mov_path = 'I:/iPhone15Pro/202310__'file_prefixes = get_matching_files(jpg_mov_path)if not os.path.exists(os.path.join(jpg_mov_path, "LivePhoto")):os.mkdir(os.path.join(jpg_mov_path, "LivePhoto"))for file_prefix in file_prefixes:dst_jpg_path = os.path.join(jpg_mov_path, "LivePhoto", f"{file_prefix}.JPG")dst_mov_path = os.path.join(jpg_mov_path, "LivePhoto", f"{file_prefix}.MOV")shutil.move(os.path.join(jpg_mov_path, f"{file_prefix}.JPG"), dst_jpg_path)shutil.move(os.path.join(jpg_mov_path, f"{file_prefix}.MOV"), dst_mov_path)fix_jpg_for_ios_import(dst_jpg_path, dst_mov_path)
嘗試過的方法
先用手上的iPhone 14 Pro Max隨便拍兩張照片,一個通過愛思導出,一個通過Windows資源管理器復制。對比一下出來的文件
很明顯這兩個文件大小差距很大。
MOV的話,文件大小一樣,算了一下md5也一樣。說明問題不在MOV上,JPG有問題。
先啟動WSL,用binwalk,foremost看一下:
binwalk IMG_4676.JPGDECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 JPEG image data, JFIF standard 1.01
34 0x22 TIFF image data, big-endian, offset of first image directory: 8
2828 0xB0C TIFF image data, big-endian, offset of first image directory: 8
2214234 0x21C95A TIFF image data, big-endian, offset of first image directory: 8
binwalk 2024_05_22_12_44_IMG_4676.JPGDECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 JPEG image data, JFIF standard 1.01
30 0x1E TIFF image data, big-endian, offset of first image directory: 8
foremost解出來兩張圖片。一張是全彩的正常圖片(00000000.jpg),攜帶大量有效metadata(例如拍攝機型、時間、GPS等)。另一張點開直接看到的是灰度圖像,沒有看到有效的metadata。
修改文件名對應MOV,導入00000000.jpg也失敗。
那么就用exiftool看一下。
exiftool -a -u -g1 IMG_4676.JPG > IMG_4676_bad.TXT
exiftool -a -u -g1 2024_05_22_12_44_IMG_4676.JPG > 2024_05_22_12_44_IMG_4676.JPG.TXT
使用Beyond Compare對比一下哪里出問題了。
存在大量不同。尤其是MP系列字段。因為本身存在2張照片
先不管MPF0字段。先嘗試直接利用exiftool復制愛思助手導出圖片的exif信息,直接覆蓋過去:
exiftool -TagsFromFile 2024_05_22_12_44_IMG_4676.JPG -all:all IMG_4676.JPG
直接成功了!
說明只需要修改這里面不同的EXIF信息即可修復導入!?
嘗試單獨修改了幾個項目,導入,無果。最終把目光看向了Apple字段下面的Media Group UUID
但是這個項目還不太好改,詢問GPT,下面這個方法不好用。
exiftool -Apple:MediaGroupUUID="E2523D1E-7C8A-423B-A8DB-53C8A073457F" IMG_4676.JPG
Warning: [minor] Maker notes could not be parsed - IMG_4676.JPG0 image files updated1 image files unchanged
?嘗試了其他的命令行修改的方法也不行。只能從文件實際內容去修改。