Порядок в фото- и видеоархиве с помощью методики и пары скриптов

    Я далеко не профессиональный фотограф, но снимать люблю, и периодически мой архив из нескольких десятков тысяч фотографий самого разного качества пополняется фотками с зеркалки, «мыльницы» и трех телефонов, а также видеозаписями с телефонов и видеокамеры. Какой я только софт не перепробовал для поддержания архива фото и видео в порядке! Adobe Lightroom, Apple iPhoto, Google Picasa…

    В итоге ни один из них не решал задачу хорошо, и пришлось писать свой. Я подумал, что мой опыт может кому-то пригодиться, из чего и родилась эта статья.

    Если вы не только фотограф, но и немножко программист, то создать подобную систему у себя вы сможете за полчаса.



    Постановка задачи

    Итак, какую же задачу мне нужно было решить? Насколько необычны мои ожидания от каталоголизатора?

    • Мне нужен механизм разбора фото по годам, месяцам и датам. Чтобы при необходимости быстро найти событие по времени.
    • Мне нужно определять дубликаты при импорте и добавлять в архив только новое.
    • Мне нужен бесплатный софт, желательно не требующий инсталляции, а в идеале еще и многоплатформенный. Идея в том, что софт должен лежать на внешнем диске вместе с фотоархивом, а запускаться с той машины, к которой этот диск подключен. Причина — требование к надежности и объему жестких дисков.
    • Мне нужен софт, который пережил бы все переустановки, смены операционной системы (даже на другую).
    • Мне нужен удобный механизм для создания резервной копии локально, при этом мне важно, чтобы бэкап не зависел от софта (то есть это была просто копия папки), и мог легко восстанавливаться целиком или по частям (подпапки).
    • Мне нужно отдельно держать RAW-версии фото (в идеале вообще на отдельном диске) и разделять их с JPG-версиями (пусть даже высокого разрешения). При этом при необходимости поднимать RAW-версию нужного файла быстро и просто. Ну и да, нужно понимать, у какого файла эта RAW-версия есть, а у какого — нет.
    • Аналогично мне нужно создавать превью видео (.AVI) для AVCHD-записей с камеры Canon (.MTS) и держать FullHD-видео (.MTS) отдельно от превью-видео (.AVI), так как FullHD занимают много места и их неудобно быстро просматривать в поисках нужного фрагмента, но когда нужно для монтажа высокое качество, было откуда достать
    • Мне нужно выкладывать фото в сеть целыми папками (Яндекс.Фотки, Facebook)
    • Иметь актуальный «мобильный архив» превьюшек с собой на мобильном телефоне, планшете, ноутбуке.


    Самые обычные требования. Наверное, в мире существует готовое ПО, позволяющее все это делать, но мне его найти не удалось. Поэтому пришлось писать самому.

    Концепция решения

    Итак, в чем состоит мой подход?

    • Никаких баз данных, проприетарного ПО. Все фото хранятся в открытой файловой системе в упорядоченном виде.
    • За упорядочивание отвечают несложные скрипты, которые можно создать для любой операционной системы и при необходимости доработать
    • Использование разных жестких дисков под разные задачи. Внешних ЖД — под тяжелые файлы (.MTS, .RAW, может, оригиналы JPG), а самого ноута под легкие возобновляемые архивы (превью). Оригиналы RAW и VIDEO могут храниться на внешнем жестком диске, так как имеют тенденцию съедать все дисковое пространство, используются крайне редко, а также потому, что важны и их жалко потерять. Оригиналы JPG хранятся либо на внешнем жестком диске, либо на локальном, если в нем есть уверенность (Raid-массив, жесткий диск настольного ПК). Превьюхи (фото и видео отдельно) хранятся на ноуте или на локальном жестком диске настольного ПК и удобны для заливки в сеть.
      Структура файловой системы под описанную выше схему:

      • Жесткий диск ноутбука, флэшка (средняя надежность)
        • IMPORT/
          • Файлики_с_флэшки/
            • IMG_2014.RAW
            • IMG_2014.JPG
            • IMG_2015.RAW
            • IMG_2016.JPG
            • MOV_0001.MOV
        • PREVIEW/
          • 2013/
            • 05/
              • 16/
                • IMG_2014.JPG
                • IMG_2015_RAW.JPG
            • 06/
              • 10/
                • IMG_2016.JPG
        • PREVIEW_VIDEO/
          • 2013/
            • 05/
              • 10/
                • MOV_0001.MOV
      • Жесткий диск ноутбука, ПК, внешний жесткий диск под нетяжелые оригиналы (высокая надежность)
        • ORIG/
          • 2013/
            • 05/
              • 16/
                • IMG_2014.JPG
                • IMG_2015_RAW.JPG
            • 06/
              • 10/
                • IMG_2016.JPG
      • Внешний жесткий диск под тяжелые оригиналы (высокая надежность)
        • RAW/
          • 2013/
            • 05/
              • 16/
                • IMG_2015.RAW
        • VIDEO/
          • 2013/
            • 05/
              • 10/
                • MOV_0001.MOV


      Папка IMPORT

      Сюда копируется все новое с фотоаппаратов и телефонов. В этой куче мы можем найти JPG-фото, RAW-фото, AVI-видео, MOV-видео в самых разных разрешениях. При обработке фото и видео переносятся из этой папки в другие (см. ниже), а старые, уже импортированные фотки, удаляются из этой папки. В итоге там может остаться какой-то мусор, который обрабатывается вручную.

      Папка ORIG

      Папка для хранения оригиналов фото в формате JPG. Для структурирования фоток и видео по годам-месяцам-дням в этой и последующих папках используется иерархия год-месяц-день. То есть, фото за 12 сентября 2004 года будут храниться в ветке ORIG/2004/09/12/. У меня имена файлов совпадают с оригинальными из IMPORT, но корректно сделать, чтобы имена файлов были уникальными, например, в форме timestamp YYYYMMDDHHMMII.JPG, чтобы не было задвоений при импорте с разных устройств.

      Папка RAW

      Если встречается RAW-фото, то проверяется, есть ли для него родной JPG-вариант, и если вдруг его нет, он создается автоматически в ORIG/YYYY/MM/DD/, а само RAW-фото переносится в RAW/YYYY/MM/DD/. При этом в имени JPG-версии в ORIG вносится указание, что для данного файла есть RAW-вариант: IMG_5905_RAW.JPG. Обычно RAW-файлы большие, поэтому эту папку имеет смысл держать на внешнем диске.

      Папка VIDEO

      Сюда переносятся оригиналы видеофайлов. Обычно они довольно большие, поэтому эту папку имеет смысл держать на внешнем диске.

      Папки PREVIEW и PREVIEW_VIDEO

      Превьюшки создаются автоматически при импорте и кладутся в свою папку PREVIEW, сохраняя иерархию, выходит что-то типа PREVIEW/2004/09/12/. Именно они скидываются на мобильные устройства для мобильного каталога фото и загружаются на фотохостинги

      Архив превьюшек я сбрасываю на мобильные устройства и периодически обновляю — обычным копированием последних по дате папок. Папку с RAW и VIDEO удобно держать на внешнем диске, так как они имеют свойство заполнять собой любой свободный объем диска, а папку с превьюхами держать на ноуте — если вдруг они потеряются из-за какого-нибудь сбоя жесткого диска или потери ноута, их всегда можно будет сделать еще раз, зато при случае можно быстро найти нужное фото или показать их друзьям.

      Особенно это ценно по отношению к FullHD-видео с видеокамеры. Для домашнего архива достаточно хранить видео экранного качества, а на случай монтажа хорошо было бы взять оригинальный MOV в Full HD — для этого подключаю внешний жесткий диск. Более того, лично у меня абсолютно все ноуты тормозят с проигрыванием Full HD MOV с камеры Canon (по крайней мере, первые несколько секунд, пока подгружается), что делает активное использование для бытовых целей оригиналов видео затруднительным. Поэтому очень удобно, когда превьюхи видео — локально, а FullHD-версии — на внешнем диске.

      А что же с событиями?

      У меня для группировки по событиям используются символические ссылки на папки по дням. То есть, поездка на Мадейру хранится в виде папки EVENTS/Мадейра/ в которой лежат папки 2012/05/01, 2012/05/02,…, 2012/05/09. Но есть несколько затруднений, которое этот подход не решает.

      Первое связано с тем, что иногда хочется связать с поездкой на Мадейру не 3500 фотографий, а пару сотен, но отобранных. Второе заключается в том, что не всегда тема четко бьется по дням. Зачастую в течение дня может быть несколько тем, а некоторые темы могут затрагивать вторую половину одного дня и первую половину следующего, в то время как остальное время этих двух дней будет относиться уже к другому событию.

      Поэтому кроме описанного выше способа есть еще два: 1) делать символические ссылки на файлы, или 2) эти файлы физическим образом копировать в папку с событием. Массового создания символических ссылок в операционной системе нет. Тем не менее, реализовать такой способ все равно реально и несложно. Физическое копирование имеет свои недостатки — одинаковые файлы начинают храниться в двух местах. Возможно, это тоже плюс — можно убить похожие фото, оставить только лучшие и т.д. Можно сделать скрипт, проходящий по файлам в обоих папках и при полной идентичности заменяющий файл на его символическую ссылку.

      Весь архив у меня хранится на жестком диске, который может быть подключен к трем компам — MacBook, компу с «виндами» и к компу с Ubuntu. Соответственно, софт должен быть в идеале совместим со всеми тремя операционками.

      Это была концепция, все, что ниже — моя (отнюдь не идеальная) реализация.

      Реализация

      Этот блок уже для тех фотографов, которым не чуждо программирование и автоматизация. Задача довольно простая и при наличии минимальных знаний о bash-скриптинге можно разобраться.

      Весь софт у меня — это два скрипта. Один обрабатывает все из папки IMPORT и раскладывает по ORIG/YYYY/MM/DD/, VIDEO/YYYY/MM/DD/, RAW/YYYY/MM/DD/ попутно создавая папки при необходимости. Второй скрипт сканирует ORIG, VIDEO, RAW и создает PREVIEW для фото и видео и кладет его в папку PREVIEW/YYYY/MM/DD.

      Импорт и раскладывание файлов по папочкам



      Для работы первого скрипта нужна утилита под названием exiftool. Она позволяет вытащить из EXIF-информации файла дату и время съемки. Ее можно найти для всех трех операционных систем. Под ubuntu она ставится из пакетов apt-get install libimage-exiftool-perl. Под Windows и MacOS скачать можно тут: http://www.sno.phy.queensu.ca/~phil/exiftool/

      В качестве инструментария разработки логики я выбрал bash scripting и perl. Во-первых, потому что он едины для MacOS и Ubuntu, а также при наличии Cygwin portable, все это заработает без существенных правок под Windows. С вашего разрешения сконцентрируюсь на MacOS и немножко на Ubuntu, и на обработке изображений, чтобы совсем не распыляться.

      Ниже я привожу сильно упрощенные скрипты, выполняющие поставленные задачи.

      Для начала разберем скрипт, добавляющий указанный файл .JPG в библиотеку:

      #./add_file_to_media_library.sh <filename> 
      


      Как видно из синтаксиса вызова, он работает с одним файлом, указанным в параметре. Небольшое ограничение для удобства — путь должен быть относительным. То есть, либо «IMG_5949.JPG» (в текущей директории), либо MYPHOTOS/IMG_5949.JPG" (в папке MYPHOTOS, которая положена в текущую директорию).

      1. export PREFIX="/Volumes/Elements/" # это путь к архиву фото. В этой папке находится ORIG
      2. export FILENAME="`pwd`/$1« # добавляем к имени файла полный путь.
      3. export OUT=`exiftool «$FILENAME» | grep "Create Date | head -n 1«`; # получаем дату создания фото из EXIF
      4. echo $OUT | grep «Create Date»;
      5. # далее создаем из даты путь вида ORIG/2013/05/01/ — куда в конечном итоге кладем файл
      6. export FOLDER=`echo $OUT | perl -i -npe "s/^(.*?): (\d+)\:(\d+)\:(\d+) (.*?)$/ORIG\/\2\/\3\/\4\//g«`
      7. # если такого пути нет, создаем его
      8. echo mkdir -p «$PREFIX$FOLDER»
      9. mkdir -p «$PREFIX$FOLDER»
      10. echo -n $FILENAME
      11. # поскольку в параметре путь может быть относительный, вытаскиваем только имя файла
      12. export NEWFILENAME=`echo $FILENAME | perl -i -npe "s/^(.*?)\/([^\/]+?)\.JPG$/\2.JPG/g«;`
      13. # проверяем, есть ли в пути вида ORIG/2013/05/01/ уже файлик
      14. if [ -f «$PREFIX$FOLDER$NEWFILENAME» ]
      15. then
      16. # есть, тогда удаляем
      17. echo «exist… $PREFIX$FOLDER$NEWFILENAME»
      18. # тут если надо, можем включить удаление из папки IMPORT
      19. # но это дело опасное, потому что целевой файл может быть битым, нулевого размера и т.д. Тогда можно потерять фото. Можно перенести файл куда-то, но я этим не заморачивался
      20. #rm $FILENAME
      21. else
      22. # если файла нет, то переносим файл из папки IMPORT в папку ORIG/YYYY/MM/DD/
      23. echo mv \"$FILENAME\" \"$PREFIX$FOLDER
      24. mv «$FILENAME» «$PREFIX$FOLDER»
      25. fi




      В итоге, весь софт у нас требует только exiftool, bash и perl и занимает несколько строк на bash. Осталось теперь создать скрипт, который будет вызывать вышеприведенный фрагмент, передавая ему параметр «имя файла». Тут есть масса способов, как это сделать, я использую

      # find . -name «*.JPG» | perl -i -npe "s/^(.*?)[\n\r]+$/\.\/add_file_to_media_library.sh \"\1\"\n/g"
      ./add_file_to_media_library.sh «./фото/IMG_5790.JPG»
      ./add_file_to_media_library.sh «./фото/IMG_5802.JPG»
      ./add_file_to_media_library.sh «./фото/IMG_5794.JPG»
      


      Соответственно, создаем add2media.sh:

      #!/bin/bash
      find . -name «*.JPG» | perl -i -npe "s/^(.*?)[\n\r]+$/\.\/add_file_to_media_library.sh \"\1\"\n/g" > /tmp/run.sh
      bash /tmp/run.sh
      rm /tmp/run.sh
      


      (BTW не очень изящное решение с созданием run.sh. можно было использовать и xargs, и -exec в find, у всего есть свои минусы и плюсы)

      Создание превью

      Для работы второго скрипта (создание превьюшек) нужна утилита, умеющая конвертировать видеофайлы и изображения. Для фото это утилита convert из пакета imagemagick (http://imagemagick.com), для видео — комплекты ffmpeg или handbrake.

      Поскольку создание превьюшек связано с конвертацией форматов, дело это небыстрое, зато не требует участия пользователя. Можно оставить на ночь, в произвольный момент прервать и при следующем запуске работа восстановится с прежней точки.

      1. #!/bin/bash
      2. #добавляем к файлу, переданному в параметре, путь к текущей директории
      3. export FILENAME="`pwd`/$1″
      4. #папка, где создан каталог PREVIEW. В моем случае — это внешний диск, можно использовать локальный
      5. export PREFIX="/Volumes/Elements/"
      6. #поскольку все файлы в ORIG уже разложены по полочкам, будем верить дате из иерархии и лишний раз не обращаться к exiftool
      7. export FOLDER=`echo $1 | perl -i -npe "s/^(.*?)\/(\d\d\d\d)\/(\d\d)\/(\d\d)\/(.*?)$/PREVIEW\/\2\/\3\/\4\//g«`;
      8. mkdir -p «$PREFIX$FOLDER»
      9. #вытаскиваем имя файла из пути
      10. export NEWFILENAME=`echo $FILENAME | perl -i -npe "s/^(.*?)\/([^\/]+?)\.JPG$/\2.JPG/g«;`
      11. echo ${PREFIX}${FOLDER}${NEWFILENAME}
      12. #создавалась ли превьюшка раньше?
      13. if [ -f «${PREFIX}${FOLDER}${NEWFILENAME}» ]
      14. then
      15. #да, создавалась. Делать ничего не надо
      16. echo «...skipped (exist) ${PREFIX}${FOLDER}${NEWFILENAME}»;
      17. else
      18. #нет, не создавалась. Надо сконвертировать
      19. echo «...convert»;
      20. convert «$infile» -auto-orient -resize 1024 -quality 85 «${PREFIX}${FOLDER}${NEWFILENAME}»
      21. fi




      Данный скрипт также предполагает передачу в качестве параметра имени файла. Для того, чтобы пройтись по всем файлам в ORIG, используется точно такой же, как в примере для раскладывания по полочкам сканер файловой системы, только вместо вызова ./add_file_to_media_library.sh там будет ./create_preview.sh

      Возможное развитие

      Отправка фотографий в Facebook и Google Picasa. У меня на этот счет также были наработки, автоматизирующие выкладку из PREVIEW. Для Facebook используется утилита FBCMD, а для создания альбомов и пакетной заливки изображений на Picasa — утилита Google Command Line Tool.

      На мой взгляд, различные «фичи» существующих каталоголизаторов, как добавление описания фотографий, теггирование, лица и проч. плохо подходят для ситуаций, когда одно событие генерит тысячу снимков и один только выбор из них важного-нужного превращается в серьезную работу. А вот использование и модификация EXIF-информации выглядит очень интересным направлением. Например, можно указать, что с 1 по 10 мая я был на Мадейре, и все снимки в ORIG в соответствующем поле EXIF приобретают географические координаты. При последующем импорте в онлайн-фотохостинги эта информация может быть считана и фотографии автоматически прикреплены к месту.

      Также очень хотелось бы, чтобы весь фото и видеоархив по ночам скидывался куда-то в защищенное облако а-ля бэкап. Это тоже довольно просто автоматизировать в описанном выше подходе, но еще не дошли руки. А какие каталоголизаторы используете вы? есть ли в них что-то нужное, что не учтено в моем подходе?

      Алиев Рауф | http://RaufAliev.ru | Facebook | LinkedIn | r.aliev@gmail.com
    Поделиться публикацией

    Комментарии 10

      0
      Добавлю штрих к решению.
      Иногда может быть удобно, если файлы не только разложены по папкам, но и сами по себе их названия несут информацию, по крайней мере, о дате и времени съемки. Лично мне, например, удобнее смотреть на имена файлов, а не на их даты в строке статуса (а full-режим в файловых менеджерах я не люблю). Для автоматического переименования по шаблону использую jhead.
        +3
        Честно говоря я так и не понял что же такого «удобного и кроссплатформенного» вы предлагаете. Раскладывание файлов по папкам вроде бы предлагают все каталогизаторы, так что тут ничего нового. Batch обработка для создания превьюх — тоже реализована почти везде. А вот удобства предложенной схемы я так и не понял.
        Вот, скажем, отсняли вы N файлов. 10% из них составил технический брак, 30% — сложные условия съемки, так что требуется дополнительная коррекция, еще 20% дублей разной степени успешности. И все эти 60% мусора стройными рядами перекочевывают в превьюхи? А потом их вычищать и их превьюх и из оригиналов? А как в вашу схему вписывается печать фотографий? Или под них еще одну структуру заводить?
          0
          для печати лично мне удобно открыть папку ORIG и через встроенные вьюеры пометить фото, которые хотелось бы напечатать. В разных ОС это разные механизмы, но как правило они или позволяют выделить файл, или скопировать его в другую папку (как правило, она носит временный характер — после скидывания в сеть или на флешку убивается).

          Насчет 60% мусора — да, у меня отправляются в превьюхи, но я лично это недостатком не считаю. Все равно людям показываешь не все, а только альбом и то чаще всего размещенным в сети. Насчет вычищать — если понадобится такая задача, то простое условие (в оригиналах стерто -> стирать из превьюх), позволит одним махом чистить обе директории.
          +1
          Как я понял от perl'а можно избавиться (dirname и basename, если в полном скрипте он больше ни для чего не используется).
          Помимо даты в каталоге я держу ещё и название события (потом вручную переименовываю), но не делаю отдельных каталогов для собрания всех дат по данному событию — слишком глубоко может быть (Место/Событие/Действующие лица и наоборот или ещё какая-нить другая иерархия, особенно в поездке в отпуск), для исключительных мест или событий завожу отдельный альбом в Picasa. Всё из-за того, что нет удобной системы тэгирования.
          Деление по дате не очень удачный способ: НГ будет разделён на 31е и 1е, хотя всё событие было 6 часов.
          Проверку идентичности файла можно сделать посчитав хэши обоих файлов, но для этого они не должны были изменяться. А иначе придётся сравнивать содержимое.

          PS: третьим будете. ;) Сам всё никак не соберусь по комментариям переделать свой скрипт (работает — не трожь!).
            +1
            Я сталкивался с той-же проблемой — raw.
            Решил другим способом (частично):
            Файлы я никуда не двигаю и никакую структуру специально не создаю. Вместо этого всю информацию (в том числе и лица, жпс, пользовательские теги… ) закидываю в EXIF заголовки. updateExifDb — обновляет базу, и выдаёт список дубликатов. И selectExifDb — позволяет по заголовкам выбрать набор картинок (потом к примеру делаю папку с кучей симлинков чтобы посмотреть на слайдшов с участием товарища Х ).
            Написано для только моего окружения. Но правильные EXIF теги позволяют заботится и о людях, которым я эти картинки даю, и о сервисах на которые выкладываю.
              0
              О, это как раз то, о чем я писал в конце статьи. Надо будет попробовать)
              +1
              когдато сделал примерно тоже самое
              exiftool прекрасно справляется с раскладыванием фотографий в дерево по дате (у меня еще и по имени камеры)
              но тут закралось две проблемы
              1. часто фотографии копируются в несколько мест по ряду причин. и потом находятся. и уже не понятно есть они в архиве или нет — имя файла изменилось. поэтому добавляем повторно. exiftool содает файлики вида имя-01.jpg (индекс автоматом растет) (имя файла у меня тоже меняется на чтото из даты-времени зачемто)
              2. зеркалка в режиме серии за секунду делает несколько кадров, которые отличить по времени уже сложно. опять exiftool создает -01 -02

              решение — написал скрипт который ищет дубликаты среди кадров с одинаковым базовым именем (не только по имени, но и по размеру и по мд5)

              в итоге все разложил. более-менее удобно
              но тут снова есть несколько проблем. пока открытых
              1. иногда в добавление попадают обработанные файлы — например уменьшил для веба, но с сохранением exif. такой «дубликат» пока не ловится. смотрю лог по размерам (1024 четко отличается от 4000)
              2. и самая большая проблема. в архиве довольно большого размера из нескольких тысяч кадров найти нужное нереально!
              возникает вопрос ведение именно каталога с тегами а комментариями. вот тут я на данный момент не нашел ничего приличного, работающего с базой превьюшек и при этом кроссплатформенного :(
              написать какоето приложение под это руки никак не доходят…
                0
                А почему вы при объявлении переменных используете export?
                Все равно они используются внутри этого скрипта и никогда не используются вне него.
                  0
                  Да, вы правы. Так, потому что отлаживал через командную строку. В скрипте убрать можно, конечно.
                  0
                  Спасибо за статью. Я как-то прошёл мимо неё, мне только что прислали ссылку.

                  Сам пользуюсь примерно таким же методом, хотя с другой внутренней структурой (там одна из проблем — много ОС в компьютерной инфраструктуре фотостудии).

                  Ваш метод наталкивает на размышления, в т.ч. о том, почему Facebook и Picasa не воспринимаются обычно как серьёзные инструменты каталогизации и архивирования фото :) (думаю, что во многом это синдром «большой чёрной зеркалки», частый у наших фотографов).

                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.