iPhone file classification by filename pattern
iOS helper: classify_iphone_file() groups photos by name pattern:
- Camera: IMG_XXXX.{HEIC,JPG} — camera originals
- Edited: IMG_EXXXX.{HEIC,JPG} — Photos.app edits
- Videos: IMG_XXXX.MOV and other video files
- Screenshots: any .PNG (iPhone camera never produces PNG)
- Screen Recordings: RPReplay_Final*.mp4
- Other: everything else (web saves, app exports, etc.)
ExifFilter.isCameraRollFolder: Camera and Edited are camera-roll,
Screenshots/Screen Recordings/Other are not.
sourceFolder now reflects these groups instead of raw DCIM folder names
(145APPLE etc.) so the left panel shows meaningful categories.
This commit is contained in:
@@ -20,6 +20,8 @@ import os
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
|
||||
import re
|
||||
|
||||
MEDIA_EXTENSIONS = {
|
||||
'jpg', 'jpeg', 'heic', 'heif', 'avif', 'webp', 'png',
|
||||
'dng', 'raw', 'arw', 'cr2', 'cr3', 'nef', 'orf', 'rw2',
|
||||
@@ -31,6 +33,35 @@ VIDEO_EXTENSIONS = {
|
||||
'mp4', 'm4v', 'mov', 'mpeg', 'mpg', '3gp', '3g2', 'avi', 'mkv', 'webm',
|
||||
}
|
||||
|
||||
# iPhone camera originals: IMG_XXXX.{HEIC,JPG,MOV} — exactly 4 digits
|
||||
CAMERA_ORIGINAL_RE = re.compile(r'^IMG_\d{4}\.(HEIC|HEIF|JPG|JPEG|MOV)$', re.IGNORECASE)
|
||||
# Edited versions: IMG_EXXXX — edited in Photos.app
|
||||
CAMERA_EDITED_RE = re.compile(r'^IMG_E\d{4}\.(HEIC|HEIF|JPG|JPEG)$', re.IGNORECASE)
|
||||
# Screenshots: PNG files (iPhone camera never produces PNG)
|
||||
SCREENSHOT_RE = re.compile(r'.*\.PNG$', re.IGNORECASE)
|
||||
# Screen recordings
|
||||
SCREEN_RECORDING_RE = re.compile(r'^RPReplay_Final.*\.mp4$', re.IGNORECASE)
|
||||
|
||||
def classify_iphone_file(filename: str) -> str:
|
||||
"""
|
||||
Returns a group name for display in the folder panel.
|
||||
Groups: 'Camera', 'Edited', 'Screenshots', 'Videos', 'Other'
|
||||
"""
|
||||
ext = filename.rsplit('.', 1)[-1].lower() if '.' in filename else ''
|
||||
if SCREEN_RECORDING_RE.match(filename):
|
||||
return 'Screen Recordings'
|
||||
if SCREENSHOT_RE.match(filename):
|
||||
return 'Screenshots'
|
||||
if CAMERA_ORIGINAL_RE.match(filename):
|
||||
if ext in ('mov',):
|
||||
return 'Videos'
|
||||
return 'Camera'
|
||||
if CAMERA_EDITED_RE.match(filename):
|
||||
return 'Edited'
|
||||
if ext in VIDEO_EXTENSIONS:
|
||||
return 'Videos'
|
||||
return 'Other'
|
||||
|
||||
|
||||
async def get_lockdown():
|
||||
from pymobiledevice3.lockdown import create_using_usbmux
|
||||
@@ -110,7 +141,7 @@ async def cmd_list_photos():
|
||||
'filename': filename,
|
||||
'sizeBytes': size_bytes,
|
||||
'dateIso': date_iso,
|
||||
'sourceFolder': folder,
|
||||
'sourceFolder': classify_iphone_file(filename),
|
||||
'mediaType': 'VIDEO' if ext in VIDEO_EXTENSIONS else 'PHOTO',
|
||||
'isHeic': ext in ('heic', 'heif'),
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user