Приложение macOS для создания серии скриншотов из видео файла.
GrabShotReview.mov
В работе медиа, при планировании рекламных роликов и фильмов, требуется создание мудборд презентаций. Презентации состоят обычно из кадров других похожих работ. Чтоб облегчить поиск и время на отсмотр вдохновляющих материалов, я решил написать приложение которое автоматизирует этот процесс. Исходные навыки дала мне школа GeekBrains, где я учюсь на разработчика iOS приложений. Бибилотеки реализации приложений на iOS и macOS одни и теже, поэтому я решил написать такую утилиту.
- Импорт серии видео файлов в приложение
- Захват изображений с заданным интервалом
- Создание штрихкода цвета для видео
- Сохранение файлов захвата на диск
- Настройки для параметров захвата
На стадии задумки я хотел чтоб пользователь мог загрзить сразу серию видео файлов и самаы быстрым и понятным способом оказался - Drag&Drop. Поэтому первое окно при запуске - это поле куда пользователь может перетащить видео файлы.
Так же есть классический способ выбрать файл через панель навигации приложения сверху "Файл -> Выбрать Видео" или горячие клавиши ⌘ + O.
На панели навигации приложения есть элемент с вкладками, чтоб пользователь мог переключаться между рабочами окнами
После импорта видео файла, приложение автоматически переключается на вкладку захвата изображений. Здесь таблица, где мы видим выбранное видео с информацией расположения файла в виде ссылки, длительность, колличество кадров захвата на выходе при текущем интервале внизу и шкала прогресса. Ниже настроек есть поле для цветового штрихкода, которое будет динамически рисоваться с каждым кадром захвата. Barcode - это цветовая палитра кадров в фильме, она отражает цветовой характер использованных цветов и оттенков в произведении. На поле штрихкода есть кнопка для просмотра штрихкода. Последняя зона - это общий прогресс очереди захвата с кнопками запуска/остановки и отмены.
При запуске процесса по кнопке Старт, начинается захват кадров. Над школой прогресса есть лог описание что происходит в данный момент, какой текущий кадр и сколько их всего.
И конечно есть возможность сделать скриншоты для всех импортированных файлов. Прогресс в таблице показывает состояние каждого, а общий всей очереди.
Получившиеся кадры в процессе сохраняются на диск в автоматически созданную папку с тем же названием что и видео файл. Местоположение папки то же что и файл. Название кадров - это название видео файла с суффиксом таймкода.
Получившийся цветовой штрихкод можно посомтреть по кнопке на его поле. Файл сохраняется тоже в папку с кадрами.
Ниже приведены несколько штрихкодов из разных фильмов.
Работу приложения можно настроить. Запуск окна для этого лежит в интуитивном месте - в верхней панели системы по нажатию на назвние программы или комюинацией ⌘ + ,.
Окно настроек делится на две вкладки.
Здесь есть ползунок для выбора степени сжатия JPG ихображений. И переключатель открытия папки с получишимися изображениями в финале процесса захвата.
Штрихкод нужен для разных задач и какой он должен быть - должен определит пользователь. На каждом кадре определяется средний цвет или цвета, их колличество можно выбрать. Разрешение конечного изображения может понадобится большим или наоборот маленьким, поэтому есть поля для размера в пикселях.
Использованные ресурсы:
Интерфейс я решил написать на SwiftUI. Причины этого решения:
- Хотелось закрепить знания этого фреймворка, которые я получил в IT школе
- Приложение не сложное, поэтому проблемы нового фреймворка по отношению не должны были возникнуть
- Синтаксис фреймворка одинаковый для мобильных приложений и для macOS
- В SwiftUI есть предикаты, которые делают код реактивным, что уменбшает колличество кода
- Научится работать с предикатами на практике
Я провел поиск подходящего мультимедиа фремворка и рассматривал следующие:
Как правило весь видео материал кино и сериалов в сети формата MKV, а встреонный AVFoundation его не поддерживает и сразу отпал.
VLCKit поддерживает MKV имеет простую документацию, написан на Objective-C. Имопртируется Pod или Package Manager. Но возникла проблема в получении серии скриншотов, они дублировались по неизвестным причинам. То есть таймкод новый в функции, а библиотека выдает прошлый кадр.
Решил попробовать FFmpeg, тут сложнее, потому что общение с фреймфорком требуется через командую строку, но это возможно. На этот раз результат был всегда точный. Есть wrapper для удобного общения в FFmpeg. Я использовал FFmpegKit.
GrabShot/GrabShot/Service/VideoService/VideoService.swift
Lines 14 to 47 in 5892b10
Серия операций захвата создается через OperationQueue
Ниже код создания очереди операций. В каждой определен completion block который будет сообщать когда операция заврешилась.
GrabShot/GrabShot/Core/GrabOperationManager/GrabOperationManager.swift
Lines 82 to 108 in 5892b10
Сама операция захвата лежит в функции main объекта Operation
GrabShot/GrabShot/Core/GrabOperationManager/GrabOperation.swift
Lines 10 to 29 in 5892b10
Так как операция pахвата происходит асинхронно, то пришлось создасть свой класс AsyncOperation наслядуюсь от Operation:
GrabShot/GrabShot/Core/GrabOperationManager/AsyncOperation.swift
Lines 10 to 62 in 5892b10
Принцип создания не сложный. Опишу его. Цветовая палитра одного кадра - это набор нескольких прямоугольников с усредненными цветам кадра выстроенных по горизонтали. Например она может выглядеть так.
Если взять несколько таких палитр, выстроить их по горизонтали, то получится очень длинная полоса с цветовыми прямоугольниками. Далее надо их сжать до ширины экрана, чтоб видеть все сруз и вот получится цветовой штрихкод. Для создания такого изображения я использовал Core Image. Функция высчитывания средних цвета изображения
GrabShot/GrabShot/Helper/NSImageExtension.swift
Lines 29 to 56 in f98c89b
Получив координаты цвета в виде Color, я создаю привычное SwiftUI view через стек прямоугольников заполненых цветом. Которые пополняются по мере обноления модели Video.
GrabShot/GrabShot/View/Elements/StripView.swift
Lines 10 to 27 in f98c89b
Сохранить получившееся вью в изорбражение можно используя ImageRenderer
GrabShot/GrabShot/Model/StripModel.swift
Lines 18 to 38 in f98c89b
- Перенести создание скриншотов для поддерживаемых форматов на встроенную библиотеку AVFoundation