Режим «картинка в картинке» на iOS: реализация и особенности — обложка

Функция «Картинка в картинке» (PiP) позволяет смотреть видео в «плавающем» окне поверх других окон — его можно перемещать по экрану и ставить в любое удобное место. Это нужно, чтобы пользователи могли следить за видео и при этом работать с другими сайтами или приложениями.

Мы уже писали о реализации PiP на Android с примерами кода. В этой статье рассмотрим iOS.

Картинка в картинке — must have современных мультимедиа-приложений

Вот почему:

  1. Обеспечивает мультизадачность. PiP позволяет пользователям одновременно просматривать видео или изображение в небольшом окне, не теряя доступа к основному контенту или интерфейсу приложения. Это даёт возможность выполнять несколько задач одновременно — например, смотреть видео и при этом проверять почту, писать сообщения или листать соцсети.
  2. Улучшает пользовательский опыт. Режим «картинка в картинке» делает навигацию по приложению более гибкой и удобной. Он значительно улучшает пользовательский опыт, потому что не требует останавливать воспроизведение контента или полностью переключаться между задачами.
  3. Минимизирует прерывание сеанса. Режим PiP позволяет пользователям продолжать смотреть видео или следить за контентом, даже когда они заняты другими задачами. Это снижает количество перерывов и делает работу более плавной и непрерывной. Например, пользователь может смотреть видеоурок или стрим на YouTube, пока ищет информацию в интернете или делает заметки.

Все эти факторы помогают удерживать пользователей в приложении и увеличивают продолжительность сеанса.

Особенности и сложности PiP на iOS

Apple выделяет два сценария использования PiP в iOS:

  • для воспроизведения видео
  • для видеозвонков

Главная проблема в том, что для сценария использования PiP для видеозвонков до iOS 16 и для iPad, которые не поддерживают Stage Manager, необходимо запрашивать у Apple специальные права на доступ к камере в режиме многозадачности com.apple.developer. avfoundation.multitasking -camera-access
И даже после нескольких месяцев ожидания — как в нашем случае — Apple все еще может не предоставить их.

Поэтому в нашем мобильном видеочате Tunnel Video Calls мы отказались от подобного сценария. Вместо этого мы выбрали другой подход: видеозвонок и его содержимое — это просто воспроизведение видео.

Жизненный цикл PiP в iOS

Режим «картинка в картинке» — это, с технической точки зрения, обмен контентом между полноэкранным приложением и PiP-окном другого приложения. Жизненный цикл такого обмена можно условно представить следующим образом:

Этапы перехода в режим “картинка в картинке” в iOS
Этапы перехода в режим «картинка в картинке» в iOS

Что происходит по порядку:

  1. Проигрывается видео в полноэкранном режиме.
  2. Пользователь инициирует событие, которое требует перехода в режим PiP. Например — нажатие на специальную кнопку или сворачивание приложения.
  3. Запускается анимация перехода видео в PiP — полноэкранный блок видео уменьшается до миниатюры и перемещается в угол экрана.
  4. Процесс перехода завершается, и приложение переходит в состояние «фон».

Затем, когда видео из Pip снова нужно вывести в полноэкранный режим, это происходит в следующем порядке:

  1. Приложение находится в фоновом режиме и отображает PiP.
  2. Происходит событие, которое запускает переход из режима «картинка в картинке» в полноэкранный режим и завершает работу PiP — например, нажатие кнопки или разворачивание приложения. Приложение переходит в Foreground.
  3. Запускается анимация перехода видео в полноэкранный режим. Приложение переходит в режим полноэкранного просмотра видео.

Как это выглядит:

Этапы выхода из режима “картинка в картинке” в iOS
Этапы выхода из режима «картинка в картинке» в iOS

Как реализовать PiP для воспроизведения видео

Чтобы PiP заработал, нужно создать объект AVPictureInPictureController(playerLayer: AVPlayerLayer). На него обязательно должна быть сильная ссылка.

 
 if AVPictureInPictureController.isPictureInPictureSupported() {
       // Create a new controller, passing the reference to the AVPlayerLayer.
         pipController = AVPictureInPictureController(playerLayer: playerLayer)     	pipController.delegate = self
             pipController.canStartPictureInPictureAutomaticallyFromInline = true}
 

Дальше нужно начать воспроизведение видео-контента

 
 func publishNowPlayingMetadata() {
   nowPlayingSession.nowPlayingInfoCenter.nowPlayingInfo = nowPlayingInfo
      nowPlayingSession.becomeActiveIfPossible()
}
 

После этого при нажатии на кнопку или сворачивании / разворачивании приложения будет запускаться PiP:

 
 func togglePictureInPictureMode(_ sender: UIButton) {
   if pipController.isPictureInPictureActive {
          pipController.stopPictureInPicture()
   } else {
       pipController.startPictureInPicture()
   }
}
 

Как реализовать PiP для видеозвонка

Рреализация режима “картинка в картинке” в iOS приложении для видеозвонков на технологии WebRTC — пожалуй, самая сложная часть работы. Мы будем рады помочь, напишите нам — обсудим детали. Идейно:

При такой реализации камера не будет снимать пользователя, и вы сможете видеть только собеседника.

Для этого нужно:

  1. Создать объект AVPictureInPictureController
  2. Получить RTCVideoFrame
  3. Получить и заполнить CMSampleBuffer на основе RTCVideoFrame
  4. Передать CMSampleBuffer и отобразить его в AVSampleBufferDisplayLayer

Вот, как это выглядит на диаграмме последовательностей:

Диаграмма последовательности реализации PiP в iOS
Диаграмма последовательности реализации PiP в iOS

  • Разработка