Миллион домашних фотографий: наводим порядок
После покупки цифрового фотоаппарата и рождения детей стало появляться большое количество фотографий, а учитывая, что жена с фотоаппаратом почти не расставалась и старалась запечатлеть все «важные» детские моменты, фотографий стало появляться ОЧЕНЬ много. Пришло время навести порядок.
Дисклеймер: вообще-то это должна была быть статья про Face Recognition, но так как исторически я начал наведение порядка с раскладывания по папкам, пришлось написать вступление, а поскольку получился такой лонгрид, что я и сам бы читать не стал, то решил разбить на две части. Итак, если вам хочется про Face Recognition, то смело пропускайте эту статью и ждите следующую.
Изначально, как и у многих наверное, фотографии просто скидывались на диск в папки с именами вида «День рождения Алисы 2010», но быстро стало ясно, что далеко не все события можно назвать так, чтобы было понятно (была бы куча папок «Алиса ест», «Алиса сидит», «Алиса идет») да и навигация по таким папкам не очень удобна.
За много лет я испробовал разные программы для работы с фотоальбомами (например, Picasa и ей подобные, с просмотром по датам, красивыми эффектами и т.д.) вот только была одна проблема, когда очередная программа «умирала» или возникало желание перейти на другую, то оставалась гора совершенно несортированных фотографий с именами типа PICT1234.JPG. В общем, стало ясно, что за основу создания каталога надо использовать, то, что относительно постоянно, а именно файловую систему. Так родилась «гениальная» структура папок и именований файлов:
Год/Год-Месяц-День (краткое описание)/Год-Месяц-День_Час-Минута-Секунда.ЖПГ
Такая структура позволяла, во-первых, быстро находить фотографии по датам и событиям привязанным к датам, во-вторых, исключала какие-либо дубликаты имен, что удобно и при последующей обработке и при передаче фотографий кому бы то ни было.
Благо цифровой фотоаппарат сохраняет метаинформацию о дате и времени съемки. Осталась самая малость: научится переносить кучу файлов с флешки на компьютер используя данную метаинформацию. На помощь пришла популярная тогда в наших краях программа ACDSee, там всего за один десяток кликов можно было переименовать файлы в нужный формат, а уж раскидать по папкам было несложно. Но как говориться — лень двигатель прогресса, и тогда на свет появился не менее «гениальный» скрипт (в то время еще bat и под «виндоус») делающий подобную операцию.
Все текло, все менялось, со временем медиатека переехала на линукс, да еще и на сервер (т.е. отдельный компьютер без монитора), а фотографий становилось все больше, так как и детей стало больше, да и сами дети тоже стали фотографировать. Пришлось «расчехлить свой питон» и создать нечто более удобное, вот об этом я и хочу тут немного рассказать.
Коротко весь процесс можно разбить на пять этапов:
Найти файлы
Извлечь метаинформацию
Переместить
Повернуть
Дети и жена не хотят пользоваться консолью (внезапно, да?)
С поиском файлов все более-менее ясно, тут справится любой школьник делающий первые шаги в Python: os.walk и иже с ним ему в помощь.
А вот с метаинформацией не все так просто. К сожалению, не все фотоаппараты выставляют EXIF и прочие метаданные. Как быть? Да, случается что информацию не извлечь никак, но часто есть подсказки, во-первых, атрибуты файла, а во-вторых имя. Многие фотоаппараты и смартфоны зашивают дату и время в имя файла. Например, IMG20180413173249204.jpg или video2017–12–28T22.13.03.mp4
Как показал опыт работы с моим набором медиа файлов, наиболее надежный источник времени съемки это EXIF, на втором месте — имя, а уж на третьем, атрибуты файла (при переписывании, например, по ftp или smb они вполне могут потеряться)
Для извлечения метаданных я использовал библиотеку exiftool. Она позволяет извлекать метаданные из всех возможных форматов, не только из EXIF, с видео и аудиофайлами она тоже отлично работает. Вычисление даты по имени файла сделал своими средствами (regexp и все такое), атрибуты файла же извлекаются стандартным инструментарием (os.stat).
Перемещение файлов можно делать «кроссплатформенно» с помощью shutil.move, а можно через вызов системной утилиты mv. К сожалению, кроссплатформенный способ работает очень медленно и импорт флешки на 32 ГБ, занимает около получаса, так что, если нужна скорость, то лучше использовать вызов системной утилиты, хоть это и не очень красиво.
Многие современные фотоаппараты сохраняют ориентацию камеры во время съемки и многие программы для просмотра изображения умеют этот тег читать, но, к сожалению, далеко не все. Так что лучше просто повернуть сразу все фотографии с учетом этого атрибута. Здесь есть свои тонкости. Во-первых, после поворота необходимо этот тег удалить (иначе будет двойной поворот в тех программах, которые тег читают), во-вторых, не хочется терять качество про повторном сохранении JPEG (к счастью JPEG поддерживает lossless rotation, но многие стандартные библиотеки работы с изображениями об этом не знают). В начале я сделал все это руками, а потом нашел отличную утилиту, которая делает все это сразу и как надо: exiftran. Так что сейчас просто вызывается она.
Казалось бы, все готово. Написал скрипт, вызвал из консоли:
photo-importer /mnt/multimedia/Import
и вот оно счастье! Но не совсем так, с начала надо открыть консоль, зайти по ssh на сервер, примонтировать флешку, найти путь монтирования, набрать команду… В общем на этом выяснилось, что импортировать так фотки буду только я сам и то по настроению.
Пришлось вспомнить азы «ХуперТекстМаркапЛенгвич», «ЖабаСкрипта» и тому подобного и написать веб-интерфейс с соответствующей ему серверной частью.
По javascript мне рассказать особо нечего, разве что, то, что я использовал горячо любимые мной библиотеки bootstrap и jquery.
А вот в серверной части немного больше интересного. Например, была задача обойтись без внешнего веб сервиса (да, у меня на сервере стоит Апач, но ведь не у всех так). Благо питон предоставляет отличные возможности для написания standalone веб сервера. Я воспользовался библиотекой http.server.
Второй интересный момент — это работа с флешками. Тут на помощь пришла утилита pmount с помощью которой можно легко монтировать внешние носители. Единственное, что осталась, так это проблема распознавания внешних носителей. В первых версиях я просто жестко «зашил» имена нужных блочных устройств в конфиг. Но, как говорится: «Шурик, это же не наш метод!» так что пришлось немного покопаться в устройствах линукса и выяснилось, что есть файл /sys/block/[имя_устройства]/removable
который содержит 1 или 0 в зависимости от того, является ли носитель внешним. А дальше — дело техники.
В итоге получился милый и лаконичный интерфейс, пригодный для использования даже с телефона, где за пару кликов можно импортировать данные с флешки, причем сразу в нужное место и с правильными именами.
А что же консоль? А консоль осталась для кастомных потребностей: прислал кто-то фотки или при наведении порядка в архиве.
Плюс там есть дополнительные возможности, например просто переименовать и повернуть файлы без перемещения.
Если кому интересны детали реализации более подробно, все исходники доступны тут.
Не думаю что эта статья кому-то «открыла Америку», но думаю может послужить примером каким образом немного автоматизировать домашнюю рутину.
В следующей статье расскажу про свои опыты с Face Recognition и про то, что из этого вышло.