-
Python/사진, 동영상 정리 V2코딩/Python 2024. 1. 23. 22:24728x90
이전 프로그램에 문제가 있었다.
사진 확인 없이 CSV로만 데이터를 변경하는 게 힘들었다. 그리고 파일이름을 시간 순서대로 변경해야 하는데 파일이름 변경하는 건 CSV에서 고려가 없었다.
파일이름은 어쨌든 사진을 보면서 순서대로 바꿔야 하니 수작업일 수밖에 없었다.
그렇게 파일이름을 바꾸고 난 뒤, 파일이름을 따라 사진은 Exif, 동영상은 생성일을 바꿔주는 방식으로 프로그램을 바꿨다.
어쩔 수 없이 command line tool인 exiftool, setfile을 썼는데, 기능은 만족스럽지만 처리속도가 느린 게 단점이다.
DATA
입력해야 하는 데이터는 여기서 모두 세팅한다.
subprocess와 call이 받을 명령어는 lamba식을 사용한다. 추후 받을 인자를 미리 세팅해 두기 위함이다. 그리고 subprocess는 데이터를 받을 때, call은 데이터를 받을 필요가 없을 때 사용한다.
DATA = { 'path':'/your/path', 'extensions_img':['.jpg', '.jpeg', '.heic', '.png'], 'extensions_mv':['.mp4', '.mov'], 'format_filename':'%y%m%d-%H%M%S', 'format_exif_time':'%Y:%m:%d %H:%M:%S', 'format_time_setfile':'%m/%d/%Y %H:%M:%S', 'cmd_get_exif_time': lambda fp: ['exiftool', '-DateTimeOriginal', fp], 'cmd_set_exif_time': lambda t, fp: ['exiftool', f'-DateTimeOriginal="{t}"', fp], 'cmd_setfile': lambda t, fp: f'SetFile -d "{t}" -m "{t}" "{fp}"' }
728x90main()
main()에서 필요한 데이터를 세팅하고 서브 프로그램을 호출한다.
def main(): path = DATA['path'] extensions_img = DATA['extensions_img'] extension_mv = DATA['extensions_mv'] format_filename = DATA['format_filename'] format_exif_time = DATA['format_exif_time'] format_time_setfile = DATA['format_time_setfile'] cmd_get_exif_time = DATA['cmd_get_exif_time'] cmd_set_exif_time = DATA['cmd_set_exif_time'] cmd_setfile = DATA['cmd_setfile'] # get file list fs_img, fs_mv = get_files(path, extensions_img, extension_mv) # modify image time fs_img_modified = modify_time_exif(path, fs_img, format_filename, format_exif_time, cmd_get_exif_time, cmd_set_exif_time) # modify movie time fs_mv_modified = modify_time_birth(path, fs_mv, format_filename, format_time_setfile, cmd_setfile) print(f'Images modified: {fs_img_modified}') print(f'Movies modified: {fs_mv_modified}')
폴더의 파일 리스트를 생성하는 get_files()
항상 쓰는 코드. 폴더 내의 파일을 리스트로 만든다. 확장자를 기준으로 디렉토리는 제거하고 이미지 파일과 동영상 파일로 구분하는 리스트를 반환한다.
def get_files(path: str, extensions_img: list[str], extensions_mv: list[str]) -> tuple[list[str], list[str]]: ''' Returns file list (files_image, files_movie) ''' fs = os.listdir(path) fs_img = [] fs_mv = [] for f in fs: _, e = os.path.splitext(f) if e.lower() in extensions_img: fs_img.append(f) elif e.lower() in extensions_mv: fs_mv.append(f) fs_img.sort() fs_mv.sort() return fs_img, fs_mv
이미지 파일의 Exif data를 수정하는 modify_time_exif()
이미지 파일(.jpg, .jpeg, .png, .heic)은 Exif를 지원하므로 Exif 데이터를 수정해서 날짜를 바꾼다.
.heic 외에는 이런 고생을 할 필요 없는데, .heic의 exif를 수정하려면 command line utility인 exiftool을 사용하는 방법이 유일하다.(내가 아는 한) 그래서 exiftool을 사용해서 exif date를 수정한다.
exiftool은 command line utility이므로 subprocess 라이브러리를 이용해서 수정한다. 단, command line utility로부터 받은 데이터는 형식을 지정하지 못하고 받은 값을 변형해야 하므로 string 데이터의 변형자를 이용해 필요한 데이터로 가공해야 한다.
또한 적절한 답을 받지 못할 수도 있으니 에러대책도 역시 코드에 포함시켜야 한다.
파일 이름의 날짜와 Exif 데이터의 날짜를 비교해서 값이 틀리면 파일 이름 날짜로 Exif 데이터를 수정한다. 이 때는 timedate 라이브러리의 time값으로 비교한다.
.heic 파일이 아닌 .jpg, .jpeg의 exif값을 수정하려면 이런 방법이 불필요하다(매우 매우 쉽다. 고민할 필요가 없다. Python의 거의 모든 라이브러리에서 수정 가능하다. 호환성이 왜 중요한지 알 수 있음). .heci가 비표준이고 저작권문제가 있어 Python의 image 관련 라이브러리가 .heic 메타데이터 수정코드를 넣지 못하고 있다. 그래서 애플폰을 사용하는 사용자들 외에는 이런 문제가 발생하지 않는다. 다만, .heic의 파일크기가 .jpeg의 1/2 또는 1/3인 걸 감안한다면(수치는 주관적) .heic로 사진들을 보관하기를 추천한다.(사진의 품질은 논외로 한다. 애플이 카메라의 기본 파일 형식을 .heic로 했기 때문에 내가 논할 일은 아니다) .hiec의 파일크기가 확실히 작기 때문에 .jpeg로 파일변환은 고려하지 않는다. (이미 애플이 결정한 순간 내 사진은 모두 .heic로 저장됐다. 그걸 .jpeg로 변환한 들 무슨 소용? ㅠㅠ)
def modify_time_exif(path: str, files: list[str], format_filename: str, format_exif_time: str, \ cmd_get_exif_time: list[str], cmd_set_exif_time: list[str]) -> list[str]: # modify date of images with exiftool fs_modified = [] for f in files: # change filename to time print(f'Processing {f}') fname, _ = os.path.splitext(f) time_fname = dt.datetime.strptime(fname, format_filename) fp = os.path.join(path, f) try: # ExifTool command: exiftool -DateTimeOriginal file/path cmd = cmd_get_exif_time(fp) # type: ignore result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True) output = result.stdout if output == '': time_exif = output else: time_string = output.partition(':')[2].strip() time_exif = dt.datetime.strptime(time_string, format_exif_time) if not time_fname == time_exif: # ExifTool command: exiftool -DateTimeOriginal='20240101-102400' file/path time_string = dt.datetime.strftime(time_fname, format_exif_time) cmd = cmd_set_exif_time(time_string, fp) # type: ignore subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True) fs_modified.append(f) except subprocess.CalledProcessError as e: print(f'Error: {e}') print(e.stderr) return fs_modified
SetFile로 파일 생성일을 변경하는 modify_time_birth()
동영상 파일은 Exif를 지원하지 않는다. 그래서 실제 파일의 생성일을 수정해야 한다.
하지만 POSIX(Mac OS)에서는 정상적인 방법으로는 파일 생성일을 수정하지 못한다. 그래서 특별한 툴, SetFile을 사용해야 한다.
Python/Mac/POSIX/SetFile로 파일 생성일 변경
사용법은 매우 쉬워 subprocess의 call()을 이용하면 간단하게 처리된다. 결과값을 따로 처리하지 않으니 더 쉽다.
def modify_time_birth(path: str, files: list[str], format_filename: str, format_time: str, call_command: str) -> list[str]: ''' SetFile로 파일생성일 변경하고 변경된 파일 목록 반환. ''' fs_modified = [] for f in files: print(f'Processing {f}') fp = os.path.join(path, f) # time from file name filename, _ = os.path.splitext(f) time_fname = dt.datetime.strptime(filename, format_filename) # time from file time_stamp = os.stat(fp).st_birthtime time_file = dt.datetime.fromtimestamp(time_stamp) if not time_fname == time_file: time_string = dt.datetime.strftime(time_fname, format_time) cmd = call_command(time_string, fp) # type: ignore subprocess.call(cmd, shell=True) fs_modified.append(f)
결론
이렇게 함으로써 파일의 관리가 쉬워졌다. 이제 GPS값을 정리하는 것이 남았다. 이미 GPS값을 처리하는 코딩은 있는데 이 프로그램과는 호환이 되지 않아 다시 작성해야 한다.
그리고, 파일의 이름과 날짜를 변경하는 프로그램도 필요한 듯 한데 그리 실용성은 높지 않은 것 같아 이 프로그램으로 미디어파일 관리를 하려고 한다.
그런데 맥과 아이폰은 특별한 구석이 있어 업무생산성은 영 좋지 않다. 역시 생산성은 MS. 내가 맨날 Mac을 쓰지만 업무용으로는 절대 비추. 외국 영화에 Mac 쓰는 건 구라다. 일 정말 못하는 인간들이나 맥 쓰는 거라고 한탄하며 본다.. 하물며 Office 프로그램도 윈도우랑 다르게 불편하다. 윈도우에선 이런 고생하지 않는다.
728x90'코딩 > Python' 카테고리의 다른 글
Python/Data 입력값, 인수, 변수 (1) 2024.02.11 Python/애플 사진(Desktop Apple Photos)/Video date & EXIF issue (0) 2024.02.01 Python/Mac/POSIX/SetFile로 파일 생성일 변경 (0) 2024.01.23 Python/터미널 출력화면을 화려하게 만들어주는 라이브러리 colorama (1) 2024.01.23 Python/애플 사진 .HEIC의 Exif 조작 - ExifTool (0) 2024.01.19