Fix photo filename collisions, video downloads, and EXIF dates
Photos in the same report with identical timestamps were overwriting each other due to missing image index in the filename. Videos failed to download because attached_video is a dict with resolution URLs, not a plain URL. Also read EXIF DateTimeOriginal before modifying the file and write the report date as fallback when the image has no original timestamp. Embed creation_time metadata in downloaded videos using ffmpeg.
This commit is contained in:
parent
0ada2d4858
commit
8413179b5f
4 changed files with 385 additions and 377 deletions
|
|
@ -4,6 +4,8 @@ import os
|
|||
import sys
|
||||
import json
|
||||
import datetime
|
||||
import shutil
|
||||
import subprocess
|
||||
import requests
|
||||
from pathlib import Path
|
||||
from PIL import Image
|
||||
|
|
@ -17,13 +19,17 @@ if not STORAGE_PATH:
|
|||
print("Error: KIDSNOTE_STORAGE_PATH is not set.")
|
||||
sys.exit(1)
|
||||
|
||||
HAS_FFMPEG = shutil.which("ffmpeg") is not None
|
||||
if not HAS_FFMPEG:
|
||||
print("Warning: ffmpeg not found. Videos will be saved without date metadata.")
|
||||
|
||||
def convert_to_degrees(value):
|
||||
degrees = int(value)
|
||||
minutes = int((value - degrees) * 60)
|
||||
seconds = (value - degrees - minutes / 60) * 3600
|
||||
return ((degrees, 1), (minutes, 1), (int(seconds * 100), 100))
|
||||
|
||||
def add_exif_data(image_path, title, content, location_str=None):
|
||||
def add_exif_data(image_path, title, content, location_str=None, fallback_date=None):
|
||||
try:
|
||||
img = Image.open(image_path)
|
||||
if 'exif' in img.info:
|
||||
|
|
@ -31,6 +37,10 @@ def add_exif_data(image_path, title, content, location_str=None):
|
|||
else:
|
||||
exif_dict = {"0th": {}, "Exif": {}, "GPS": {}, "1st": {}, "thumbnail": None}
|
||||
|
||||
if fallback_date and not exif_dict['Exif'].get(piexif.ExifIFD.DateTimeOriginal):
|
||||
dt_str = fallback_date.strftime("%Y:%m:%d %H:%M:%S")
|
||||
exif_dict['Exif'][piexif.ExifIFD.DateTimeOriginal] = dt_str.encode('utf-8')
|
||||
|
||||
if location_str:
|
||||
try:
|
||||
latitude, longitude = map(float, location_str.split(','))
|
||||
|
|
@ -93,10 +103,35 @@ for date, reports in sorted(reports_by_date.items()):
|
|||
|
||||
if report.get('attached_video'):
|
||||
try:
|
||||
r = requests.get(report['attached_video'])
|
||||
video = report['attached_video']
|
||||
video_url = video.get('high') or video.get('low') if isinstance(video, dict) else video
|
||||
r = requests.get(video_url)
|
||||
r.raise_for_status()
|
||||
with open(folder / f"V_{report_index}.MP4", "wb") as f:
|
||||
f.write(r.content)
|
||||
video_path = folder / f"V_{report_index}.MP4"
|
||||
if HAS_FFMPEG:
|
||||
temp_video = folder / f"temp_V_{report_index}.MP4"
|
||||
with open(temp_video, "wb") as f:
|
||||
f.write(r.content)
|
||||
# Check if the video already has a creation_time
|
||||
probe = subprocess.run([
|
||||
"ffprobe", "-v", "quiet", "-show_entries",
|
||||
"format_tags=creation_time", "-of", "csv=p=0",
|
||||
str(temp_video)
|
||||
], capture_output=True, text=True)
|
||||
if probe.stdout.strip():
|
||||
temp_video.rename(video_path)
|
||||
else:
|
||||
report_datetime = datetime.datetime.strptime(report['created'], "%Y-%m-%dT%H:%M:%S.%fZ")
|
||||
creation_time = report_datetime.strftime("%Y-%m-%dT%H:%M:%S.000000Z")
|
||||
subprocess.run([
|
||||
"ffmpeg", "-y", "-i", str(temp_video),
|
||||
"-metadata", f"creation_time={creation_time}",
|
||||
"-c", "copy", str(video_path)
|
||||
], capture_output=True)
|
||||
temp_video.unlink()
|
||||
else:
|
||||
with open(video_path, "wb") as f:
|
||||
f.write(r.content)
|
||||
except requests.RequestException as e:
|
||||
print(f"Video download failed: {e}")
|
||||
|
||||
|
|
@ -108,15 +143,17 @@ for date, reports in sorted(reports_by_date.items()):
|
|||
with open(temp_path, "wb") as f:
|
||||
f.write(r.content)
|
||||
|
||||
add_exif_data(temp_path, report['child_name'], report['content'], report.get('location'))
|
||||
|
||||
dt = get_creation_datetime(temp_path)
|
||||
|
||||
report_datetime = datetime.datetime.strptime(report['created'], "%Y-%m-%dT%H:%M:%S.%fZ")
|
||||
add_exif_data(temp_path, report['child_name'], report['content'], report.get('location'), fallback_date=report_datetime)
|
||||
|
||||
if dt:
|
||||
date_str = dt.strftime("%Y-%m-%d_%H-%M")
|
||||
else:
|
||||
date_str = date.strftime("%Y-%m-%d")
|
||||
|
||||
final_name = f"P{report_index}_{date_str}.jpg"
|
||||
final_name = f"P{report_index}_{img_index}_{date_str}.jpg"
|
||||
final_path = folder / final_name
|
||||
|
||||
temp_path.rename(final_path)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue