拍摄了很多年的视频和照片后,我越来越积累。自孩子出生以来,它进一步加速发展,文件数量已超过90,000,并且已超过300GB,仅在智能手机上包含照片和视频。连同视频一起,它是750GB,已接近OneDrive的上限,因此我决定充分利用它并进行组织。
环境
- MacBook Air 2014年末
- Python 3.7
- ffmpeg
- ffprobe
- 微软OneDrive
您想在本系列中做什么
程序
如果执行上述步骤,将组织OneDrive中已同步的照片,并且容量会减少。万岁
OneDrive的优缺点
建议使用Microsoft的OneDrive备份照片。我认为有很多人订阅Office 365以使用必需的Office,但是当您订阅Office 365时,将自动附加1 TB的OneDrive容量。
OneDrive方便了照片备份
OneDrive照片备份
有什么问题
* 1该规范在几年前得到了改进,现在每年和每月自动保存在一个文件夹中。这是长期使用它的用户所特有的问题。
这个非常有问题。如果您在专用的智能手机应用程序或浏览器上查看它,它具有一项功能,可让您按拍摄日期和时间的时间顺序浏览,但是如果您要查明特定的年份和月份,则无论如何显示都很沉重,而且,它仅在文件夹单元中是本地的。由于它无法与计算机同步,因此当您要在本地将文件夹与照片同步并执行各种操作时,如果您有成千上万张照片,则将需要等待大量时间仅使用finder或ls命令。
1.与OneDrive应用程序
中的外部驱动器同步
mac软件无法像在设置中一样将外部驱动器设置为同步目标文件夹。考虑各种各样的事情很麻烦,所以我用符号链接解决了它。
如果您已经是第一次运行OneDrive文件夹,请转到"首选项"中的"帐户"标签,然后单击"取消链接此Mac"以停止同步。
接下来,在连接外部驱动器之后,在外部驱动器中创建一个OneDrive文件夹,然后在主文件夹中创建一个符号链接。
1 2 3 | cd mkdir -p /Volumes/[外付けドライブデバイス名]/OneDrive ln -s /Volumes/[外付けドライブデバイス名]/OneDrive ~/OneDrive |
完成后,再次使用OneDrive应用登录,并在同步文件夹选择中的主文件夹中指定OneDrive符号链接,以安全地进行同步。
2.使用Python
读取和排序文件夹中的所有照片和视频的程序
本文只写要点,因此,如果您需要所有资料,请参见github
https://github.com/mychaelstyle/photofles_sorter
从JPEG
读取EXIF
使用枕头
1 2 3 4 5 6 | from PIL import Image from PIL.ExifTags import TAGS img = Image.open([file path]) exif = img._getexif() img.close() |
这会将EXIF项目的标签ID和值集的数组加载到exif中。
由于此处读取的标签ID是数字值,因此如果要检查EXIF的项目名称(例如DateTimeOriginal),则需要从导入的TAGS中获取项目名称。
1 2 3 4 5 | labeled_items = [] for id, value in exif.items(): tag_name = TAGS.get(id,id) labeled_item = ( tag_name, value ) labeled_items.append(labeled_item) |
现在,您有一个由多个元组组成的数组,但就我而言,我只需要知道拍摄日期,因此我将仅提取DateTimeOriginal。
1 2 3 4 5 6 | dt_origin = None for id, value in exif.items(): tag_name = TAGS.get(id,id) if tag_name == "DateTimeOriginal": dt_origin = value break |
我能够安全地获得拍摄日期
获取的拍摄日期是字符串" 2019:10:08 12:00:00",是用冒号分隔的陌生格式,但是在(ymd,hms)= dt_origin.split(),ymd.split之后就可以了如果您使用(":")创建具有不同日期的文件夹路径字符串。
1 2 | (ymd, hms) = dt_origin.split() (year, month, day) = ymd.split(":") |
从佳能原始文件(.CR2)
中读取拍摄日期
请参阅此规范
http://lclevy.free.fr/cr2/
由于需要
字节操作,因此请使用struct。
1 | from struct import * |
我会省略它,因为如果我写各种各样的东西会很长,但是简单地说,字节序,CR2版本和固定信息都包含在文件的开头,而第16个字节中的信息是基本信息项的数量。已保存。用于保存项目数的数据长度是固定的,如上面的URL中所述。
首先,读取字节顺序是小字节序还是大字节序
使用unpack_from从结构读取第一个字节作为数字。请注意,unpack_from返回为包含每个字节的值的元组,而与字节数
无关
1 2 3 4 5 6 7 8 9 | with open(path, "rb") as f: buffer = f.read(1024) (byte_order) = unpack_from('H', buffer) # Set the endian flag endian_flag = '@' if byte_order == 0x4D4D: endian_flag = '>' elif byte_order == 0x4949: endian_flag = '<' |
获取条目数并循环查找代表dateTime项目
的数字0x0132
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | (num_of_entries,) = unpack_from(endian_flag+'H', buffer, 0x10) for entry_num in range(0,num_of_entries): (tag_id, tag_type, num_of_value, value) = unpack_from(endian_flag+'HHLL', buffer, 0x10+2+entry_num*12) if tag_id == 0x0132: assert tag_type == 2 assert num_of_value == 20 datetime_offset = value break datetime_strings = unpack_from(20*'c', buffer, datetime_offset) datetime_string = "" for str in datetime_strings: datetime_string += str.decode() print(datetime_string) |
现在您可以使用类似2019:10:07 12:00:00的格式获取日期!
获取视频文件的拍摄日期和时间.mov / .3gp / .mp4
获取iPhone的MOV视频,.mp4,旧版Android和Garake的3gp视频以及数码摄像机的.mp4文件的拍摄日期。
我在python3中没有一个好的库,所以我不得不采取尴尬的方式放置ffmpeg和ffprobe并使用子进程进行攻击??用Homebrew安装ffmpeg和ffprobe
1 2 | brew install ffmpeg brew install ffprobe |
在Python中,用子进程
命中
1 2 3 4 5 6 7 8 9 | import subprocess proc = subprocess.run(["/usr/local/bin/ffprobe","-show_chapters","-hide_banner",path], stdout = subprocess.PIPE, stderr = subprocess.PIPE) response = proc.stdout.decode("utf8")+"\n"+(proc.stderr.decode("utf8")) for line in response.splitlines(): if "creation_time" in line: str = line.replace(" creation_time : ","").replace("T"," ").replace("Z","") print(str) break |
这是一个粗略的方法,但是我能够处理所有视频格式。
如果您想要一个可以正常运行的程序,请访问github。
https://github.com/mychaelstyle/photofles_sorter
组织程序
在2019-10阶段,上面的github程序将保留隐藏的文件以及不移动它们就无法获取拍摄日期和时间的文件。另外,如果目的地处已经存在具有确切名称,文件大小以及拍摄日期和时间的文件,则该文件将不会被移动并且不会被更改。
移动或跳过的执行结果也作为日志输出到执行文件夹中。
我按照以下过程整理了文件。
由于呼出日志的格式是固定的,因此可以按以下方式进行检查。文件名以info-year-month-day-hours-hours,minutes,seconds.log格式输出。
1 2 3 4 | # 隠しファイルではなく撮影日時を取得できなかったファイルのログ一覧 cat info-YYYY-MM-DD-HHmmss.log | grep "No timestamp" | grep -v "/\." # 隠しファイルではなく重複していたので移動しなかったファイルのログ一覧 cat info-YYYY-MM-DD-HHmmss.log | grep "Same file" | grep -v "/\." |
3.检测并删除文件名称不同但内容相同的文件
到目前为止,该过程中不再包括文件名称,拍摄日期和时间以及文件大小完全相同的重复文件。
问题是删除了在OS下载,OneDrive上传和备份时批量生产的具有不同文件名的相同照片和视频。
选择不覆盖时,使用**(1).JPG等数字创建的文件。
照片复制检测
我们将在第二集中进行。等待!下期!