有关使用python等组织在OneDrive上拉屎的照片和视频的故事。


拍摄了很多年的视频和照片后,我越来越积累。自孩子出生以来,它进一步加速发展,文件数量已超过90,000,并且已超过300GB,仅在智能手机上包含照片和视频。连同视频一起,它是750GB,已接近OneDrive的上限,因此我决定充分利用它并进行组织。

环境

  • MacBook Air 2014年末
  • Python 3.7
  • ffmpeg
  • ffprobe
  • 微软OneDrive

您想在本系列中做什么

  • 我想为年份和月份创建一个文件夹,以分隔过去在一个文件夹中备份的所有数据。
  • 我想通过删除由于备份或手动上传错误导致的重复文件来减少容量。
  • 我想为每个文件夹可以保存的照片数量设置一个上限,以便可以流畅地显示它们。
  • 当显示变得平滑时,我想通过删除未经许可备份的无意义和离焦的图像来减少容量
  • 程序

  • 使用适用于您计算机的同步应用程序将照片文件夹同步到本地计算机的外部驱动器
  • 创建一个Python程序,该程序自动在photo文件夹中创建一个year / month文件夹并对照片进行排序,然后执行该程序,以使相同的文件名在过去不会被覆盖。
  • 创建一个重复的检测python程序,并删除文件名不同但内容相同的文件。
  • 在检测相似性并进行目视检查的同时删除不必要的文件
  • 如果执行上述步骤,将组织OneDrive中已同步的照片,并且容量会减少。万岁

    OneDrive的优缺点

    建议使用Microsoft的OneDrive备份照片。我认为有很多人订阅Office 365以使用必需的Office,但是当您订阅Office 365时,将自动附加1 TB的OneDrive容量。

    OneDrive方便了照片备份

  • 照片不会变质!
  • 随附1TB的Office 365
  • iOS和Android均可使用该应用程序自动备份照片
  • 即使在Windows / Mac OS上,也有一个本地应用程序可以自动保存
  • 与Goxxle和Axxzon照片不同,它可以存储大量数据而不会降低图像质量。
  • OneDrive照片备份

    有什么问题

  • 对于iOS和Android,所有照片和视频都保存在同一文件夹(* 1)中
  • 无需标记或搜索人员姓名(比Google方便)
  • 帐户不如Google广泛,难以共享
  • * 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程序将保留隐藏的文件以及不移动它们就无法获取拍摄日期和时间的文件。另外,如果目的地处已经存在具有确切名称,文件大小以及拍摄日期和时间的文件,则该文件将不会被移动并且不会被更改。
    移动或跳过的执行结果也作为日志输出到执行文件夹中。

    我按照以下过程整理了文件。

  • 创建一个新文件夹以将图像和照片聚合到OneDrive同步文件夹中。
  • 将上述文件夹指定为分发照片和视频的每个文件夹的输出目的地,然后执行它。
  • 在查看每个移动源的日志时,删除重复的文件,保存必要的文件,然后删除移动源文件夹。
  • 由于呼出日志的格式是固定的,因此可以按以下方式进行检查。文件名以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等数字创建的文件。

    照片复制检测

    我们将在第二集中进行。等待!下期!