スマホやデジカメで撮った思い出の写真。Googleフォトで保管していたものの、ある日ふとダウンロードしてみたら、撮影日時がバラバラに崩れていた──そんな経験はありませんか?
Googleフォトのエクスポート機能(Google Takeout)を使うと、写真や動画をまるごとダウンロードできますが、ファイルの「作成日」や「変更日」がパソコンに保存した日になってしまい、アルバムが時系列で並ばなくなることがあります。
これは、エクスポートされた写真や動画のファイルそのものには撮影日時の情報(Exifデータなど)が含まれていない、もしくは正しく引き継がれていないためです。
実は、エクスポート時に一緒に保存される「metadata.json」ファイルに、本来の撮影日時などの情報がちゃんと記録されているんです。
この記事では、そのmetadata.jsonを活用して、PythonとExifToolというツールを使い、撮影日時を一括で元通りに修正する方法をご紹介します。
プログラムの操作がありますが、初心者の方でも使えるようにわかりやすく解説しています。思い出を正しい順番で整理したい方に、ぜひ読んでいただきたい内容です。
Googleフォトからエクスポートすると撮影日時が崩れる理由
Googleフォトに保存していた写真や動画を、Googleのエクスポート機能(Google Takeout)で一括ダウンロードすると、ファイルの「作成日」や「変更日」がパソコンに保存した日付になってしまうことがあります。macOSのFinderなどでは、これがそのまま「撮影日時」として表示されてしまうため、写真が時系列で並ばなくなり、見返すのがとても不便になります。
このようなズレが起きるのは、エクスポートされたファイル本体に「撮影日時(Exifデータ)」が正しく引き継がれていないためです。写真や動画の中には、元々メタデータが存在しない場合や、クラウド上で一部の情報が欠損しているケースもあります。
ですが安心してください。Google Takeoutでは、この問題を補うために、各ファイルに対応する「metadata.json」というファイルも一緒に保存されるようになっています。このJSONファイルの中には、元の撮影日時や位置情報などがしっかりと記録されており、それを活用すれば撮影日時を正確に復元することができます。
では、このmetadata.jsonを使って、どうやって撮影日時を一括で修正するのか?次の章では、その具体的な方法をご紹介していきます。
撮影日時のズレを一括で修正するベストな方法
Googleフォトのエクスポートで崩れてしまった撮影日時を手作業で直すのは、現実的ではありません。写真や動画が数百枚、数千枚にもなると、1つ1つの情報を確認して編集するのは非常に手間がかかりますし、ミスも起きやすくなります。
そこで活躍するのが、metadata.jsonの撮影日時情報をもとに、Exifデータを一括で書き換える自動処理スクリプトです。この記事では、Pythonというプログラミング言語と、ExifToolという高機能なメタデータ編集ツールを組み合わせて、写真や動画の撮影日時をまとめて元通りに復元する方法を紹介します。
Pythonを使うことで、フォルダ内のファイルを1枚ずつ処理し、対応するJSONファイルの内容を読み取って、ExifTool経由でメディアファイルに撮影日時を書き込むことが可能になります。しかも、日時だけでなく位置情報やタイトル、人物タグ(キーワード)なども反映できるため、ただの修正ではなく「写真情報の復元」に近い作業が実現できるのです。
また、ExifToolは信頼性が高く、多くの写真・動画フォーマットに対応しているため、Googleフォトからのエクスポートファイルにも問題なく使うことができます。スクリプトを一度用意すれば、次回からはフォルダを指定するだけで撮影日時の復元とファイル整理が一括で完了します。
次のセクションでは、この方法を実際に使うために必要な準備やインストール手順をご紹介していきます。
必要な準備|Python + ExifTool のインストールと基本環境
macOS環境での事前準備(Homebrew活用)
撮影日時の修正を自動で行うには、PythonとExifToolという2つのツールが必要です。どちらも無料で使えるうえ、Mac環境なら簡単に導入できます。
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
次に、ExifToolとPythonをHomebrewでインストールします。
brew install exiftool
brew install python
さらに、macOSでファイルの作成日を変更するために使う SetFile コマンドを有効にするには、Appleのコマンドラインツール(Command Line Tools)もインストールしておきましょう。
xcode-select --install
スクリプト実行の流れと、ファイルの配置方法
スクリプトを使うためには、Googleフォトからエクスポートした写真や動画ファイルと、それに対応するJSONファイルを同じフォルダに配置しておく必要があります。
📥 配置すべきファイルの例
• IMG_0001.JPG(メディアファイル)
• IMG_0001.JPG.supplemental-metadata.json(対応するメタデータファイル)
• IMG_0002.MOV
• IMG_0002.MOV.supplemental-metadata.json
この「.supplemental-metadata.json」という拡張子は、Googleフォトのエクスポート仕様で自動的に付くもので、ファイル名の先頭はメディアファイルと一致しています。
📁 フォルダ構成のイメージ:
作業フォルダ/
├─ IMG_0001.JPG
├─ IMG_0001.JPG.supplemental-metadata.json
├─ IMG_0002.MOV
├─ IMG_0002.MOV.supplemental-metadata.json
├─ script.py
このフォルダで script.py を実行することで、JSONに記録された撮影日時・位置情報・タグ情報などをメディアファイルに書き込み、さらに自動でフォルダ整理まで行ってくれます。
スクリプトの実行方法(ターミナル)
ターミナルを開き、スクリプトのあるフォルダに移動して以下を実行します:
cd /Users/yourname/Desktop/作業フォルダ # 作業フォルダに移動
python3 script.py # スクリプトを実行
📂 処理後のフォルダ構成イメージ:
処理が完了すると、以下のようにファイルが自動で整理されます:
作業フォルダ/
├─ 取込済み/
│ └─ JSON/
│ ├─ IMG_0001.JPG.supplemental-metadata.json
│ └─ IMG_0002.MOV.supplemental-metadata.json
└─ X/
└─ 2023/
└─ 12/
├─ IMG_0001.JPG
└─ IMG_0002.MOV
• 撮影日時は metadata.json の photoTakenTime.formatted に基づいてExifに反映されます
• メディアファイルは撮影年・月ごとのフォルダ(例:X/2023/12/)に自動で振り分け
• JSONファイルは「取込済み/JSON」にまとめられ、作業フォルダがスッキリ整理されます
このように、一度スクリプトを準備しておけば、次回からは同じ手順で複数ファイルを一括処理できるようになります。次のセクションでは、実際に使用するスクリプトのコードとその使い方を詳しくご紹介していきます。
撮影日時を一括修正するPythonスクリプトを紹介
ここでは、metadata.jsonに記録された撮影日時をもとに、写真や動画ファイルのExif情報を一括で書き換えるPythonスクリプトをご紹介します。このスクリプトは以下のような処理を自動で行ってくれます:
• メディアファイルと同名の .supplemental-metadata.json を検索して対応付け
• JSONから撮影日時(photoTakenTime)を抽出
• ExifToolを使ってExifの DateTimeOriginal, CreateDate, ModifyDate に反映
• 緯度・経度・高度があればGPS情報として書き込み
• 人物名(people)やタイトル(title)もキーワードやタイトルに追加
• 撮影日時をもとに X/年/月/ フォルダへファイルを移動
• JSONファイルは「取込済み/JSON」フォルダに整理
• macOSの作成日・変更日も撮影日時に変更(SetFile使用)
(※ スクリプト内容は記事内で掲載・解説)
🧾 スクリプト全文
import os
import json
import subprocess
import shutil
import datetime
import time
# 対応する拡張子
SUPPORTED_EXTS = [".jpg", ".jpeg", ".mov", ".mp4", ".png",".avi"]
root_dir = r'ここでフォルダを指定してください'
# 作業ディレクトリ
base_dir = root_dir
# JSON保存先
processed_json_dir = os.path.join(root_dir, "JSON")
os.makedirs(processed_json_dir, exist_ok=True)
# メディア保存ベース(Xフォルダ)
X_base_dir = root_dir
def is_valid_datetime(dt_str):
return isinstance(dt_str, str) and dt_str.count("/") == 2 and "UTC" in dt_str
def is_valid_float(value):
try:
float(value)
return True
except (ValueError, TypeError):
return False
def run_exiftool(args, filepath):
cmd = ["exiftool"] + args + ["-overwrite_original", filepath]
subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def set_file_timestamps(filepath, datetime_str):
try:
dt = datetime.datetime.strptime(datetime_str, "%Y:%m:%d %H:%M:%S")
timestamp = time.mktime(dt.timetuple())
os.utime(filepath, (timestamp, timestamp))
formatted = dt.strftime("%m/%d/%Y %H:%M:%S")
subprocess.run(["SetFile", "-d", formatted, "-m", formatted, filepath])
except Exception as e:
print(f"{filepath}: 作成日・変更日の更新に失敗しました: {e}")
# メディアファイルの処理
for filename in os.listdir(base_dir):
name, ext = os.path.splitext(filename)
ext = ext.lower()
if ext in SUPPORTED_EXTS:
media_path = os.path.join(base_dir, filename)
# JSONを前方一致 + .jsonで検索
json_path = None
for f in os.listdir(base_dir):
if f.startswith(filename) and f.endswith(".json"):
json_path = os.path.join(base_dir, f)
break
if not json_path or not os.path.exists(json_path):
print(f"{filename}: 対応する JSON ファイルが見つかりません。スキップします。")
continue
with open(json_path, "r", encoding="utf-8") as f:
try:
metadata = json.load(f)
except json.JSONDecodeError:
print(f"{filename}: JSON の読み込みに失敗しました。スキップします。")
continue
args = []
date_str = None
year = month = None
# 撮影日時
photo_time = metadata.get("photoTakenTime", {}).get("formatted", "")
if is_valid_datetime(photo_time):
date_str = photo_time.replace("/", ":").replace(" UTC", "")
args += [
f"-DateTimeOriginal={date_str}",
f"-CreateDate={date_str}",
f"-ModifyDate={date_str}"
]
# 年・月の抽出
dt = datetime.datetime.strptime(date_str, "%Y:%m:%d %H:%M:%S")
year = str(dt.year)
month = f"{dt.month:02}"
else:
print(f"{filename}: 撮影日時が不正か存在しません。")
# 緯度・経度・高度
geo = metadata.get("geoDataExif", {})
lat = geo.get("latitude")
lon = geo.get("longitude")
alt = geo.get("altitude", 0.0)
if lat is not None and lon is not None and is_valid_float(lat) and is_valid_float(lon):
lat = float(lat)
lon = float(lon)
if lat != 0.0 and lon != 0.0:
args += [
f"-GPSLatitude={lat}",
f"-GPSLongitude={lon}",
f"-GPSAltitude={alt if is_valid_float(alt) else 0.0}",
"-GPSLatitudeRef=N" if lat >= 0 else "-GPSLatitudeRef=S",
"-GPSLongitudeRef=E" if lon >= 0 else "-GPSLongitudeRef=W"
]
else:
print(f"{filename}: 緯度・経度が不正または存在しないためスキップ。")
# タイトル
title = metadata.get("title", "")
if isinstance(title, str) and title.strip():
args.append(f"-Title={title.strip()}")
# 人物タグ
people = metadata.get("people", [])
if isinstance(people, list):
for person in people:
name = person.get("name", "").strip()
if name:
args.append(f"-Keywords={name}")
else:
print(f"{filename}: people データが不正です。")
# ExifTool 実行
if args:
run_exiftool(args, media_path)
print(f"{filename}: メタデータを適用しました。")
if date_str:
set_file_timestamps(media_path, date_str)
else:
print(f"{filename}: 適用可能なメタデータがありませんでした。")
# メディアファイルの保存先を決定(X/年/月)
if year and month:
media_dest_dir = os.path.join(X_base_dir, year, month)
os.makedirs(media_dest_dir, exist_ok=True)
shutil.move(media_path, os.path.join(media_dest_dir, os.path.basename(media_path)))
else:
print(f"{filename}: 年月が不明なためメディアファイルを移動できませんでした。")
# JSONを保存
shutil.move(json_path, os.path.join(processed_json_dir, os.path.basename(json_path)))
print(f"{filename}: メディア → X/{year}/{month}/、JSON → 取込済み/JSON に移動完了。")
📝 使い方のポイント
• スクリプトファイルは script.py などの名前で保存
• python3 script.py で実行
• 事前に exiftool、python3、SetFile(macOS) をインストールしておく
🛠 スクリプト実行時のチェックポイント
チェック内容 | 解説 |
---|---|
JSONがメディアと一致しているか? | IMG_0001.JPG → IMG_0001.JPG.supplemental-metadata.json のようにペアになっていること |
撮影日時がJSON内にあるか? | photoTakenTime.formatted が正しい形式で含まれていること |
ファイルの拡張子が対象か? | .jpg, .jpeg, .mov, .png のみ対応(.heicは除外) |
このスクリプトを実行するだけで、ファイルのExif撮影日時が一括で正しく修正され、Mac上でも正しい順に写真を整理できるようになります。
次のセクションでは、スクリプトを使う際によくあるトラブルや注意点についてご紹介します。
スクリプト使用時の注意点とよくあるトラブル
このスクリプトはとても便利ですが、すべてのケースで完全にうまく動作するとは限りません。特に、初めて使う際にはいくつかのポイントに注意することで、トラブルを未然に防ぐことができます。
JSONに撮影日時がない場合はどうなる?
エクスポートされた .supplemental-metadata.json の中には、まれに photoTakenTime が存在しないものや、形式が崩れているファイルがあります。
このような場合、スクリプトはそのファイルをスキップし、エラーを出さずに次のファイルへ進むようになっています。
🔍 補足:撮影日時がないファイルは、フォルダ分類(年/月)ができないため、移動対象にもなりません。
ExifToolが書き込みに失敗する場合の対処法
ExifToolがメタデータを書き込めない場合、以下のような原因が考えられます:
原因 | 解決策 |
---|---|
ファイルに書き込み権限がない | chmod +w ファイル名 で書き込み許可を付与 |
ExifToolがインストールされていない | brew install exiftool を確認 |
パスの通し忘れ(環境による) | which exiftool で確認し、フルパス指定で呼び出すことも可能 |
ファイル形式が非対応(例:HEICなど) | HEICは別記事で対応予定(このスクリプトでは対象外) |
SetFileで「Permission denied」となる場合
macOSで作成日や変更日を変更する際、SetFile を使いますが、初回は権限の確認が表示される場合があります。
その場合は、ターミナルやPythonスクリプトに「フルディスクアクセスの権限」を与えることで回避できます。
このような注意点を理解しておくことで、スムーズにスクリプトを活用できるようになります。
次のセクションでは、撮影日時を復元することで得られる整理のメリットや、今後の写真管理をもっと楽にするアイデアをご紹介します。
撮影日時が正しく戻ることで得られるメリット
撮影日時がちゃんと整っていると、写真や動画の整理がとてもラクになりますよね。
ただ並び順が正しくなるだけではなくて、「この日何があったかな?」と振り返るときの満足度もぐっと上がります。
Macの写真アプリやFinderでの並び順が復活
macOSの写真アプリやFinderでは、撮影日時をもとに写真が自動で並ぶようになっています。
ですが、Googleフォトからエクスポートしたファイルは保存した日付が「作成日」になってしまうため、時系列がバラバラになってしまうんですよね。
Exifの撮影日時を修正しておけば、Macの中でも本来の順番で写真が表示されるようになります。
旅行やイベントの思い出も、自然な流れで振り返ることができて、気持ちよく整理できますよ。
GoogleフォトやiCloudに再アップしても順番が崩れない
修正したファイルをGoogleフォトやiCloudにもう一度アップロードしても、撮影日時が正しく読み込まれるようになります。
クラウドでも撮影日をもとに並ぶようになるので、アップ後の整理も安心ですよね。
とくに家族で共有しているアルバムや、Googleフォトの検索機能をよく使う方にはうれしいポイントです。
写真整理の負担がぐっと減る
撮影日時が正確に入っていれば、それをもとに年ごと、月ごとにフォルダで分けることもできますし、タグやタイトルを活用すれば検索性もぐんとアップします。
今まで手作業で1枚ずつ確認して並べ替えていた作業が、ほんの数分で終わるようになるんです。
写真がどんどん増えていく今、こうした自動整理の仕組みを取り入れておくと、後々とても助かりますよ。
たったひとつの日時情報が正しいだけで、写真の「見やすさ」「思い出のつながり方」がまったく違ってきます。
日付の修正は地味な作業に見えて、実はとても大事な一歩なんですね。
まとめ|写真整理は「撮影日時の復元」から始めよう
Googleフォトからエクスポートした写真や動画の撮影日時が崩れてしまうのは、よくあるトラブルのひとつです。ですが、metadata.jsonに記録された情報を活用することで、元の正しい撮影日時を取り戻すことができます。
今回ご紹介したPythonスクリプトを使えば、ファイルを手動で開いたり編集したりすることなく、まとめてExifの撮影日時を修正できるようになります。Macの写真アプリやFinderで時系列に並ぶのはもちろん、iCloudやGoogleフォトに再アップロードしても、崩れることなくそのまま反映されるのがうれしいですよね。
思い出の写真がたくさんあるからこそ、最初に撮影日時を整えておくと、あとからの整理や活用がぐっとラクになります。「いつ」「どこで」「誰と」という記録が正しく残っていることで、写真の価値もぐんと高まります。
もし今、お手元に「時系列がバラバラになった写真フォルダ」があるなら、ぜひ今回の方法を試してみてください。思い出を、きちんと整えて残すための第一歩になるはずです。
ここまでお読みいただきありがとうございました。それではまた次の記事でお会いしましょう。
それじゃまたね、ばいばいっ!
コメント