先日紹介した写真管理ソリューションのImmichですが、バージョン1.95.1では、PCからアップロードする際、ブラウザで直接アップロードできますし、しかも次のように、同時アップロードを随時調整できて、とても効率的で柔軟です。
しかし、ちょっとした問題として、アップロードの時にファイルしか選択できません。
日付ごとのフォルダに分けられた写真をアップロードしたいですが、フォルダを選択できないです。
数年分の写真がありますので、日ごとに選択するのは結構骨が折れる作業になりそうです。
そこで調べたところ、APIが用意されており、公式では「Python File Upload」のサンプルまで用意されてます。
ファイルごとのアップロードではありますが、最近話題のGeminiの力を借りてフォルダごとアップロードのPythonスクリプトを作りましたのでこちらで共有します。
APIキー作成
Immichの管理画面にログインしたら、次のように操作すればAPIキーを作成できます。
APIキーは作成直後の画面でしか表示されないようですので、お忘れなく保存しておきましょう。
アップロードのPythonスクリプト
ソースは以下です。アップロードはマルチスレッドで行います。
#!/usr/bin/python3
import requests
import os
from datetime import datetime
from concurrent.futures import ThreadPoolExecutor
API_KEY = 'YOUR_API_KEY' # 上で作ったAPIキーに置き換えてください
BASE_URL = 'http://127.0.0.1:2283/api' # ご自身の環境に合わせて変更してください
def upload(file):
stats = os.stat(file)
headers = {"Accept": "application/json", "x-api-key": API_KEY}
data = {
"deviceAssetId": f"{file}-{stats.st_mtime}",
"deviceId": "python",
"fileCreatedAt": datetime.fromtimestamp(stats.st_mtime),
"fileModifiedAt": datetime.fromtimestamp(stats.st_mtime),
"isFavorite": "false",
}
files = {"assetData": open(file, "rb")}
response = requests.post(
f"{BASE_URL}/asset/upload", headers=headers, data=data, files=files
)
print(response.json())
# {'id': 'ef96f635-61c7-4639-9e60-61a11c4bbfba', 'duplicate': False}
print(f"アップロード成功: {file} ({os.path.getsize(file)} bytes)")
def main(dirpaths):
# アップロード対象となるファイル一覧を取得
file_paths = []
for dirpath in dirpaths:
for dirpath, dirnames, filenames in os.walk(dirpath):
file_paths.extend(
[os.path.join(dirpath, filename) for filename in filenames]
)
# マルチスレッド処理
with ThreadPoolExecutor(max_workers=os.cpu_count()) as executor:
executor.map(upload, file_paths)
if __name__ == "__main__":
# スクリプトの引数を受け取る
import sys
dirpaths = sys.argv[1:]
main(dirpaths)
上記のスクリプトをimmich-upload.py
というファイル名だとすれば、次のように実行できます。
python immich-upload.py <フォルダパス1> <フォルダパス2> <フォルダパス3> ...
実行結果は次のようになります。
{'id': '9f66a2d7-3bfd-4fc8-8139-41377728cf79', 'duplicate': False}
アップロード成功: <パス>/<ファイル名> (<ファイルサイズ> bytes)
同じファイルを2回目以降アップロードされた場合、上記結果の’duplicate’はTrueになりますが、エラーになることはありません。
コメントを残す