Я подхожу к приложению для съемки как к оптическому прибору, заключенному в стекло и алюминий. Пользователь видит кнопку записи и миниатюру галереи, инженер видит граф захвата, поток CMSampleBuffer, синхронизацию аудио с видео, метаданные матрицы и поведение сенсора при нехватке света. Хороший результат начинается не с интерфейса, а с точного ответа на вопрос: какой класс задач решает продукт. Один сценарий опирается на быстрый запуск камеры и мгновенный кадр. Другой строится вокруг ручного контроля экспозиции, серии снимков, LOG-видео, LUT-преобразований и экспорта в ProRes. Третий делает ставку на предметную съемку, где ценность рождается из макродистанции, коррекции дисторсии и чистого контура объекта.

AVFoundation

Первый технический слой — AVFoundation. Для фото и видео Apple дает зрелый набор компонентов: AVCaptureSession, AVCaptureDevice, AVCaptureDeviceInput, AVCapturePhotoOutput, AVCaptureVideoDataOutput, AVCaptureMovieFileOutput, AVCaptureAudioDataOutput, AVCaptureMetadataOutput. Я предпочитаю схему, где сессия собирается из входов и выходов под конкретный режим, а переключение между фото и видео не ломает граф захвата. Непродуманная реконфигурация рождает задержки, скачки экспозиции и потерю фокуса. Сессия камеры любит дисциплину: begin Configuration, изменение параметров, commitConfiguration. Такой порядок работает как шлюз в гидросистеме — открыл в нужный момент, поток прошел без турбулентности.

Архитектура захвата

На старте проекта я разделяю домены: Camera Core, Media Pipeline, UI Layer, Storage, Export. Camera Core управляет устройствами, разрешениями, частотой кадров, фокусом, зумом, вспышкой, torch-режимом. Media Pipeline обрабатывает буферы, таймстемпы, конвертацию пиксельных форматов, предпросмотр, запись. UI Layer живет отдельно от камеры, иначе экранный код быстро превращается в клубок состояний. Storage отвечает за Photo Library, временные файлы, sandbox, каталогизацию сессий. Export собирает медиа в финальный контейнер, накладывает фильтры, добавляет цветовые преобразования, звук, субтитры, watermark.

Для интерфейса я часто беру SwiftUI как внешний слой и связываю его с UIViewRepresentable для предпросмотра камеры через AVCaptureVideoPreviewLayer. Чистый UIKit ничем не хуже, зато предсказуем в деталях анимации и работы с layout при поворотах. Важнее не набор фреймворков, а ясная граница между экраном и железом. Камера не любит, когда ее дергают из десятка мест. Один coordinator или actor управляет сессией, сериализует команды, хранит текущее состояние. Для Swift Concurrency такой подход особенно удобен: меньше гонок, меньше случайных блокировок, чище логика смены камеры и режима записи.

Подбор устройств внутри iPhone редко сводится к фронтальной и основной камере. В AVFoundation доступны широкоугольная, сверхширокоугольная, телеобъектив, TrueDepth. На части моделей есть virtual device — логическая камера, объединяющая несколько физических модулей. Здесь появляется термин disparity map — карта смещений между ракурсами, на основе которой система оценивает глубину. Для портретных задач глубина полезна не ради размытия фона, а ради точной сегментации волос, стекла, тонких контуров предмета. Если продукт работает с предметной съемкой или AR-наложениями, глубинные данные меняют качество результата заметнее любого фильтра.

Фото и видео живут по разным правилам. Фото тянется к максимальному качеству единичного кадра: RAW, bracketed capture, обработка шумов, EXIF/JPEG, глубина, semantic segmentation mattes. Видео держится за устойчивость потока: частота кадров, битрейт, тепловой режим, длительная запись без пропусков. Когда команда пытается собрать оба режима на одном наборе настроек, камера отвечает компромиссом, а компромисс редко дружит с качеством. Я закладываю отдельные профили сессии: photo, video, high frame rate, cinematic preview. Каждому профилю соответствует свой preset, набор выходов и стратегия постобработки.

Управление камерой

Фокус и экспозиция — сердце съемки. Автоматика iPhone работает хорошо, но приложение с ручным контролем выигрывает у стандартной камеры в предсказуемости. Для фокуса доступны continuous AutoFocus, autoFocus, locked. Для экспозиции — continuousAutoExposure, custom, locked. Пользовательский тап по экрану переводится в pointOfInterest в координатах сенсора, а не в координатах вью. Ошибка в преобразовании координат делает интерфейс обманчивым: рамка фокуса прыгает в одну точку, резкость уходит в другую. Я всегда связываю жесты с реальной геометрией preview layer и проверяю поведение на разных aspect ratio.

Есть редкий, но крайне полезный набор данных — Camera Calibration Data. Он включает intrinsic matrix, extrinsic параметры и сведения об оптике. Проще говоря, матрица внутренних параметров описывает, как камера “смотрит” на сцену: фокусное расстояние в пикселях, положение главной точки, геометрию проекции. Для компьютерного зрения, трекинга объектов, точного наложения графики такая информация ценнее десятка ручных правок. Если приложение сочетает съемку с анализом кадра, калибровка превращается в камертон, по которому выстраивается вся визуальная логика.

Зум на iPhone — отдельная история. Часть значений цифровая, часть оптическая, часть проходит через fusion между модулями. Резкий скачок изображения при пересечении границы между линзами раздражает сильнее, чем ограниченный диапазон приближения. Я строю шкалу зума с учетом videoZoomFactorUpscaleThreshold и доступных переключений между устройствами. Пользователь чувствует непрерывность, даже если внутри идет смена физической камеры. Здесь полезна метафора коробки передач: хороший интерфейс не заставляет водителя думать о шестернях, он дает ровный ход.

Баланс белого редко обсуждают вне профессиональной среды, а зря. Человек прощает легкую мягкость кадра, но странный оттенок кожи замечает сразу. В AVFoundation доступен режим lockWithDeviceWhiteBalanceGains. Gains — коэффициенты усиления по каналам, с их помощью сцена перестает “гулять” между теплыми и холодными оттенками при движении камеры. Для предметной съемки, каталога товаров, съемки пищи ручной баланс белого критичен. Для репортажного сценария я предпочитаю гибрид: автоматический анализ в начале эпизода, затем фиксация до конца клипа.

Стабилизация в видео выглядит простой функцией, пока не начинается борьба за минимальную задержку предпросмотра. AVCaptureConnection даёт режимы стабилизации, но у каждого своя цена в латентности и кадрировании. Если продукт ориентирован на блоггинг или репортаж, небольшая дополнительная задержка не мешает. Если интерфейс строится вокруг точной синхронизации жестов с картинкой, задержка ломает ощущение прямого контакта с камерой. Я всегда измеряю end-to-end latency: от движения сцены до ее появления на экране. Удобство записи рождается не из рекламного перечня функций, а из этого невидимого интервала.

Потоки и кодеки

Видео захватывается в буферы, а не в “ролики”. Базовая единица работы — CMSampleBuffer. Внутри лежат таймстемпы, ссылки на CV Pixel Buffer, сведения о формате, синхронизация. Когда разработчик начинает мыслить буферами, камера перестает казаться черным ящиком. Предпросмотр, запись, фильтрация, детекция объектов, стриминг — разные маршруты одного потока данных. Я часто строю fanout pipeline: один буфер идет в preview, второй в записи, третий в Vision или Core Image. Тут нужна аккуратная работа с очередями и памятью, иначе кадры копятся как ледяная крошка в трубке и душат fps.

Формат пикселей задает характер всей обработки. BGRA удобен для части графических операций. YUV, чаще biplanar 420f/420v, экономнее и ближе к реальному видеопотоку. Если впереди H.264 или HEVC, работа в YUV снижает лишние конверсии. Если нужны фильтры в Metal и сложный compositing, выбор зависит от конкретной цепочки. Я избегаю бессистемных преобразований между форматами. Каждое перекодирование — как перешивка паруса во время шторма: лодка еще идет, но ткань уже теряет прочность.

Для записи видео доступны H.264, HEVC, на поддерживаемых моделях ProRes. H.264 совместим почти со всем. HEVC дает меньший размер при том же визуальном качестве, но повышает нагрузку на декодирование в старых средах. ProRes занимает много места, зато сохраняет материал для монтажа и цветокоррекции без лишней компрессии. Выбор кодека нельзя сводить к цифрам битрейта. Надо смотреть на целевую аудиторию, длину клипа, способ доставки, монтажный сценарий. Клип для мгновенной отправки в мессенджер и мастер-файл для постпродакшна живут в разных экосистемах.

Фото форматы несут свои компромиссы. JPEG прост и привычен. HEIF экономит место и поддерживает современную структуру контейнера. RAW в формате DNG хранит сырой сигнал сенсора, дает огромный запас для обработки, но требует иной UX: пользователь ждет от RAW не мгновенного “глянца”, а материала для последующей работы. В приложении для энтузиастов и профессионалов я часто сохраняю пару: превьюшный HEIF плюс DNG. Для обычного сценария достаточно HEIF с корректным color profile и внятной обработкой шарпинга.

Цвет в iOS-приложении для съемки нельзя оставлять “на глаз”. Color space, transfer function, gamut, HDR metadata — набор понятий, от которых зависит, увидит ли пользователь тот же кадр после экспорта и отправки. Rec.709 годится для стандартного SDR-видео. Display P3 хранит расширенный цветовой охват. Для HDR-видео Apple использует свои комбинации кодирования и метаданных. Ошибка здесь напоминает расстроенный оркестр: каждый инструмент звучит прилично, но вместе музыка распадается. Я явно фиксирую цветовое пространство на входе и выходе, проверяю предпросмотр, экспорт, отображение в Photos и сторонних приложениях.

Звук в приложениях ккамеры часто недооценен. Пользователь готов простить чуть менее эффектную картинку, если речь чистая и ровная. Для звука я настраиваю AVAudioSession с нужной категорией, слежу за route change, учитываю Bluetooth, проводные микрофоны, встроенные капсулы. Если сценарий завязан на интервью, полезен контроль уровней, индикатор перегруза, high-pass filter для борьбы с гулом. Синхронизация аудио и видео строится на временных метках, без нее длинные записи плывут, а губы начинают жить своей жизнью. Мелкая рассинхронизация разрушает доверие к продукту быстрее, чем любой баг в декорациях интерфейса.

Обработка и экспорт

Обработка в реальном времени на iPhone давно вышла за пределы “наложить фильтр”. Core Image, Metal, Vision, Accelerate, Core ML открывают путь к шумоподавлению, сегментации, тоновой компрессии, ретуши, слежению за объектом, стабилизации по движению. Но каждый новый шаг в пайплайне поднимает температуру устройства, а тепло — скрытый режиссер мобильной съемки. Когда система уходит в thermal throttling, падает fps, сужается выбор режимов, растут задержки. Я проектирую обработку как каскад с несколькими ступенями качества: full, balanced, low power. Устройство само подсказывает, где начинается перегрев, инженер обязан услышать.

Для монтажа и экспорта используется AVAssetWriter, AVAssetExportSession, AVMutableComposition, AVVideoComposition. Если задача — записать поток как есть, AVAssetWriter дает прямой и гибкий контроль. Если нужна сборка из нескольких клипов, титры, музыка, переходы, правка таймлайна, на сцену выходит композиция. Я предпочитаю не путать live capture с последующим export pipeline. Смешение режимов рождает хрупкий код, где запись и рендер делят ресурсы без ясной очередности. Гораздо надежнее сначала завершить захват, зафиксировать медиафайл, потом выполнять экспорт в фоновом процессе с понятным отчетом о прогрессе.

Тонкая тема — rolling shutter, “желейность” изображения при быстром движении. Сенсор считывает строки не мгновенно, а последовательно, из-за чего вертикали наклоняются, кадр будто течет. Полностью убрать артефакт на уровне приложения нельзя, но его влияние уменьшается выбором частоты кадров, выдержки, режимов стабилизации, аккуратной постобработкой. Для интерфейса полезно дать пользователю ясные сигналы: 24 fps для кинематографичности, 30 fps для универсального сценария, 60 fps для движения и спорта. Частота кадров здесь похожа на ритм сердца сцены: слишком низкая — кадр спотыкается, слишком высокая — исчезает фактура времени.

Работа с Photo Library строится через Photos framework. Я предпочитаю явное разделение: временный файл пишется в sandbox, затем после подтверждения сохраняется в медиатеку. Такой маршрут дает контроль над ошибками, откатом, повторной попыткой, поведением при ограниченном доступе к библиотеке. С введением limited library access пользователь выбирает, что именно открыть приложению. Интерфейс обязан уважать этот выбор и не вести себя как взломщик у двери архива. Чем прозрачнее логика доступа, тем меньше трения и выше доверие.

Метаданные нужны не ради галочки. EXIF, GPS, ориентация, настройки экспозиции, модель устройства, профиль цвета, длительность, timecode — все это влияет на поиск, ссовместимость, последующую обработку. Для профессионального сценария полезен embedded timecode, если дальше материал идет в монтажную систему. Для каталога товаров цены структурированные пользовательские поля. Для социальной съемки уместно очищать часть приватных сведений перед экспортом. Метаданные — не мусор в контейнере, а паспорт кадра.

Тестирование камеры нельзя свести к симулятору. Настоящая проверка проходит на устройстве, лучше на нескольких поколениях iPhone. Я гоняю сценарии в ярком солнце, в сумерках, при смешанном свете, с движением, с длинной записью, с переключением линз, с входящими звонками, с блокировкой экрана, с заполненной памятью, с подключенным микрофоном, с AirPods, с ограниченным доступом к Photos, с перегревом. Отдельно смотрю холодный старт, warm start, восстановление после ошибки media services where reset. Камера капризна, но каприз системный: если карта сбоев собрана тщательно, продукт ведет себя достойно даже под нагрузкой.

Производительность упирается в дисциплину памяти. Буферы нельзя копировать без нужды, крупные изображения нельзя держать в RAM дольше необходимого, тяжёлые фильтры нельзя запускать на главной очереди. CVMetalTextureCache, pixel buffer pools, reuse-стратегии, сжатие превью, ленивый декод — инструменты, которые спасают приложение от внезапной одышки. На уровне UX я избегаю мгновенного показа “идеальной” миниатюры ценой фриза интерфейса. Лучше дать честный, быстрый отклик, а детализацию дорисовать через долю секунды.

Безопасность и приватность формируют тон общения с пользователем. Разрешения на камеру, микрофон, фотобиблиотекаку запрашиваются в момент, когда смысл действия очевиден. Текст причины доступа пишется человеческим языком, без тумана. Если продукт обрабатывает медиа локально и не отправляет его на сервер, я говорю об этом прямо. Если загрузка в облако есть, схема хранения, удаления и шифрования описывается ясно. Для творческого приложения доверие работает как чистая оптика: без него даже сильный функционал дает мутное впечатление.

Если подвести инженерный контур, хорошее iOS-приложение для фото- и видеосъемки рождается на пересечении трех дисциплин: понимание камеры как физического прибора, уважение к ограничениям мобильного устройства и аккуратная продуктовая логика. Кнопка записи — вершина айсберга. Под ней живут сенсор, линзы, автофокус, потоки буферов, кодеки, цветовые пространства, звук, экспорт, фоновые очереди, права доступа, тепловой режим. Когда эти слои настроены в одном ключе, приложение перестает быть набором экранов и превращается в точный инструмент. Я ценю именно такие продукты: они не спорят с реальностью железа, а извлекают из нее чистый, уверенный кадр.