Picture-in-Picture (PiP) — режим воспроизведения видео в плавающем окне поверх других приложений, позволяющий пользователю продолжать просмотр контента при сворачивании приложения или переключении между программами. PiP-окно автоматически позиционируется в углу экрана и может быть перемещено пользователем. По данным Apple AVPictureInPictureController documentation (2026), PiP-режим поддерживается на iOS начиная с версии 14 и на Android с версии 8.0.
Главное
Picture-in-Picture (PiP) — это режим отображения видео в маленьком плавающем окне, которое остаётся поверх всех других окон и приложений. Пользователь может перемещать окно PiP по экрану, изменять его размер (на некоторых платформах) и продолжать просмотр контента при работе в других приложениях.
Концепция PiP пришла из телевидения: ещё в 1990-х годах телевизоры позволяли показывать второй канал в углу экрана. В мобильных устройствах PiP впервые появился на iPad в iOS 9 (2015 год) для видео в Safari, а полноценный системный PiP для приложений стал доступен в iOS 14 (2020). На Android поддержка PiP появилась раньше — в версии 8.0 Oreo (2017), но только для видео, а начиная с Android 12 — для любых типов контента.
PiP отличается от фонового воспроизведения тем, что видео продолжает отображаться на экране, а не только воспроизводиться в аудиопотоке. Фоновое воспроизведение (background audio) доступно на обеих платформах, но PiP даёт пользователю визуальный контроль над контентом: он видит кадры, может поставить на паузу, перемотать или закрыть окно. Это особенно важно для видеоуроков, стримов и видеозвонков, где визуальный контент не менее важен, чем аудио.
Архитектурно PiP реализуется через системный менеджер окон, который создаёт отдельное окно с пониженным приоритетом отображения. Приложение делегирует видеовыход системному сервису, который продолжает рендеринг видео даже после того, как приложение переходит в фоновый режим или сворачивается.
Процесс начинается, когда пользователь сворачивает приложение с активным видео или нажимает кнопку PiP (на iOS) или система автоматически переводит Activity в режим PiP (на Android). Системный менеджер окон захватывает видеопоток и создаёт плавающее окно с фиксированными пропорциями. Размер окна зависит от соотношения сторон исходного видео и ограничений платформы: на iOS PiP-окно занимает примерно 1/6–1/4 ширины экрана, на Android — не менее 108 dp в ширину и 240 dp в высоту для мобильных устройств.
Когда PiP-окно активно, приложение может находиться в одном из трёх состояний: в фоне (свёрнуто), в активном состоянии (пользователь вернулся к приложению), или в состоянии ожидания (система приостановила PiP из-за нехватки ресурсов). При переходе в PiP приложение должно приостановить ненужные UI-операции (анимации, рендеринг интерфейса) и освободить память, так как системные ресурсы в многозадачном режиме распределяются более жёстко. iOS автоматически отправляет приложению уведомление AVPictureInPictureControllerWillStartNotification, а Android — колбэк onPictureInPictureModeChanged.
PiP-окно имеет существенные ограничения: на нём нельзя отображать стандартные UI-элементы управления (кнопки паузы, ползунок прогресса) — только минимальный системный оверлей с базовыми элементами: play/pause, закрыть, развернуть на полный экран. Системный UI PiP на iOS включает кнопку паузы и закрытия, а на Android — те же элементы плюс дополнительную кнопку для настроек. Взаимодействие с контентом внутри PiP (перемотка, выбор субтитров) невозможно — для этого нужно развернуть приложение на полный экран.
На iOS PiP реализован через фреймворк AVKit и класс AVPictureInPictureController. Этот API доступен на iOS 14+ для iPhone и iPad, но с разными требованиями: на iPad PiP работает через AVPlayerLayer, на iPhone — только через AVPlayerViewController.
Для работы PiP на iOS необходимо выполнить несколько условий: приложение должно использовать AVPlayer для воспроизведения видео, audio session должна быть настроена на категорию .playback или .playAndRecord, и приложение должно иметь entitlements для фонового аудио (UIBackgroundModes = audio). Без этих настроек PiP не запустится — система отклонит запрос на создание сессии PiP, так как не сможет гарантировать корректное воспроизведение после перехода в фоновый режим.
На iOS PiP-окно автоматически показывается при сворачивании приложения, если видео активно воспроизводится и пользователь не отключил эту функцию в настройках. Пользователь может также вручную свернуть видео в PiP через кнопку в AVPlayerViewController. Размер PiP-окна на iOS фиксирован и определяется системой — разработчик не может его изменить. Соотношение сторон PiP-окна соответствует соотношению сторон исходного видео, но максимальный размер ограничен 1/4 ширины экрана на iPhone и 1/3 на iPad.
Основные ограничения PiP на iOS: невозможность кастомного UI в PiP-окне, ограничение на один PiP-поток одновременно, и требование активного AVPlayer для работы PiP. Multi-PiP — одновременное воспроизведение нескольких PiP-окон — не поддерживается на iOS. При попытке запустить второй PiP первый автоматически закрывается. Это ограничение аппаратное: видеопроцессор не может одновременно обслуживать два независимых PiP-канала из-за ограничений DMA и видеопамяти.
Ещё одно важное ограничение — длительность воспроизведения в фоне. Если пользователь не взаимодействует с PiP-окном, система может приостановить воспроизведение через некоторое время для экономии энергии. Автоматическая пауза PiP на iOS наступает через 10–15 минут неактивности, если приложение не реализовало keep-alive механизм через background task. Для видеозвонков и стримов рекомендуется использовать PushKit и VoIP-сертификаты, которые обходят это ограничение.
На Android PiP реализован как встроенный режим Activity, который активируется через метод enterPictureInPictureMode. Начиная с Android 8.0 (API 26), любая Activity может перейти в PiP-режим, а с Android 12 (API 31) появилась поддержка PiP для SurfaceView и TextureView без необходимости использования MediaCodec.
Для поддержки PiP в манифесте Android необходимо указать атрибут android:supportsPictureInPicture для Activity в разделе
В Android PiP-окно по умолчанию не имеет элементов управления. Разработчик может добавить кастомные действия через RemoteAction в методе setPictureInPictureParams. Доступно до 3 действий (например: пауза/плей, перемотка назад/вперёд, закрытие). Каждое действие отображается в системном оверлее PiP в виде иконки. В отличие от iOS, где все UI-элементы строго фиксированы, Android даёт больше гибкости для базовых контролов.
PiP на Android имеет разные возможности в зависимости от версии ОС. На Android 8.0–8.1 PiP доступен только для видео, воспроизводимого через MediaPlayer или MediaCodec с SurfaceView. Начиная с Android 9 можно использовать PictureInPictureArgs.Builder для настройки соотношения сторон PiP-окна. Android 12 добавил поддержку PiP для кастомных SurfaceView и TextureView, а также улучшенное управление переходами между полноэкранным и PiP-режимом. Android 13+ позволяет отображать PiP-окно даже при заблокированном экране, если приложение имеет соответствующее разрешение.
| Версия Android | Возможности PiP | API |
|---|---|---|
| 8.0–8.1 | Базовый PiP для MediaPlayer/MediaCodec | 26–27 |
| 9–11 | Настройка соотношения сторон, кастомные действия | 28–30 |
| 12 | Поддержка SurfaceView/TextureView в PiP | 31 |
| 13+ | PiP на экране блокировки, улучшенные анимации | 33+ |
Ключевое отличие Android PiP от iOS — возможность multi-PiP. На Android с версии 12 система может показывать несколько PiP-окон одновременно, если приложения это поддерживают и производительность устройства позволяет. Однако на практике multi-PiP ограничен возможностями SoC: большинство устройств поддерживают только одно PiP-окно из-за аппаратных ограничений декодера, так как каждое PiP-окно требует собственного видеопотока и отдельного сеанса декодирования.
Рассмотрим практическую реализацию PiP на обеих мобильных платформах с учётом последних изменений API.
import AVKit
import AVFoundation
class VideoPlayerViewController: UIViewController {
var player: AVPlayer!
var pipController: AVPictureInPictureController?
override func viewDidLoad() {
super.viewDidLoad()
let playerLayer = AVPlayerLayer(player: player)
playerLayer.videoGravity = .resizeAspect
view.layer.addSublayer(playerLayer)
guard AVPictureInPictureController.isPictureInPictureSupported()
else { return }
pipController = AVPictureInPictureController(playerLayer: playerLayer)
pipController?.delegate = self
}
@IBAction func startPiPTapped() {
pipController?.startPictureInPicture()
}
}
extension VideoPlayerViewController: AVPictureInPictureControllerDelegate {
func pictureInPictureControllerWillStart(
_ pictureInPictureController: AVPictureInPictureController
) {
// Скрыть UI-элементы, освободить память
}
func pictureInPictureControllerDidStop(
_ pictureInPictureController: AVPictureInPictureController
) {
// Восстановить UI, возобновить рендеринг
}
}
В примере AVPictureInPictureController инициализируется с playerLayer после проверки isPictureInPictureSupported (PiP не поддерживается на iPhone SE 1-го поколения и некоторых iPad без достаточной памяти). Делегат уведомляет приложение о начале и завершении PiP — в этих колбэках нужно скрыть и восстановить UI-элементы, так как в PiP-режиме интерфейс приложения не виден. При переходе в PiP рекомендуется остановить все анимации, скрыть контролы плеера и освободить неиспользуемую память для предотвращения принудительной выгрузки приложения системой.
class PipVideoActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setupVideoPlayer()
}
private fun enterPipMode() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val aspectRatio = Rational(16, 9)
val pipParams = PictureInPictureParams.Builder()
.setAspectRatio(aspectRatio)
.setAutoEnterEnabled(true)
.build()
enterPictureInPictureMode(pipParams)
}
}
override fun onPictureInPictureModeChanged(
isInPictureInPictureMode: Boolean,
newConfig: Configuration
) {
if (isInPictureInPictureMode) {
// Скрыть UI, фокусироваться только на медиа
binding.controlsGroup.visibility = View.GONE
} else {
// Восстановить UI
binding.controlsGroup.visibility = View.VISIBLE
}
}
}
Пример на Kotlin использует PictureInPictureParams.Builder для настройки PiP. Метод setAspectRatio задаёт соотношение сторон PiP-окна (16:9 для типичного видео). setAutoEnterEnabled(true) включает автоматический переход в PiP при сворачивании приложения. Колбэк onPictureInPictureModeChanged вызывается при входе и выходе из PiP — в нём следует скрывать или показывать UI-элементы. Для видео на SurfaceView требуется дополнительно обработать конфигурацию, добавив android:configChanges="screenSize|smallestScreenSize" в манифест, чтобы предотвратить пересоздание Activity при переходе в PiP-режим.
PiP — мощный инструмент для улучшения пользовательского опыта в приложениях, где контент остаётся релевантным даже при переключении на другие задачи. Однако внедрение PiP должно быть обоснованным и не отвлекать пользователя.
Видеозвонки и конференции — один из главных сценариев PiP. В Zoom, FaceTime, Google Meet PiP позволяет видеть собеседника во время работы с другими приложениями: чтения заметок, просмотра презентации или проверки почты. PiP для видеозвонков требует поддержки камеры в фоновом режиме и правильной настройки audio session для продолжения захвата аудио в фоне. На iOS для этого используется AVSampleBufferDisplayLayer вместо AVPlayerLayer, так как видеозвонки не используют AVPlayer.
Стриминговые сервисы (YouTube, Netflix, Twitch) активно используют PiP для продолжения просмотра во время поиска нового контента. YouTube Premium предлагает PiP как платную функцию, Netflix также ограничивает PiP определёнными тарифными планами из-за лицензионных ограничений контента. Для реализации PiP в стриминговом приложении требуется интеграция с DRM-системой (FairPlay, Widevine), которая поддерживает безопасный pipeline в PiP-режиме.
PiP не подходит для приложений с интерактивным видеоконтентом, где требуется взаимодействие пользователя: образовательные платформы с тестами внутри плеера, игровые стримы с чатом, приложения для покупок с ссылками на товары в видео. В этих случаях PiP-окно слишком мало для отображения дополнительной информации, а интерактивные элементы в PiP не поддерживаются системой. Рекомендуется использовать PiP только для пассивного просмотра, когда взаимодействие с контентом не требуется.
Для музыкальных и подкаст-приложений PiP избыточен — достаточно фонового аудио без визуального окна. PiP потребляет дополнительные ресурсы GPU для рендеринга видео в плавающем окне, что сокращает время автономной работы. Если контент аудиальный (музыка, подкасты, аудиокниги) — используйте фоновое воспроизведение без PiP. Если визуальный — внедряйте PiP для улучшения пользовательского опыта.
Часто задаваемые вопросы
PiP на iOS требует iPhone 6s+, iOS 14+ и регион с поддержкой (США, Канада, Австралия, ЕС, Россия и другие). Для приложения необходимо настроить audio session на категорию .playback и добавить UIBackgroundModes = audio. Также проверьте настройки: Настройки > Основные > Картинка в картинке.
На iOS размер PiP-окна полностью определяется системой и не настраивается разработчиком. На Android можно задать только соотношение сторон через setAspectRatio в PictureInPictureParams.Builder, но точный размер окна определяет система. Пользователь может изменить размер PiP-окна на Android 12+ жестом pinch-to-zoom.
Да, PiP работает с DRM-защищённым контентом (FairPlay на iOS, Widevine L1 на Android) при условии, что DRM-сессия поддерживает защищённый pipeline в PiP-режиме. Widevine L3 может не поддерживать PiP, так как не гарантирует безопасность декодированного контента в плавающем окне. Проверяйте совместимость DRM с PiP на этапе тестирования.
На iOS — только одно PiP-окно. На Android 12+ теоретически поддерживается multi-PiP, но на практике большинство устройств ограничены одним окном из-за аппаратных ограничений. Toп-устройства (Samsung Galaxy S24, Pixel 8) могут поддерживать 2 PiP-окна, но с пониженной производительностью.
Да, обработка lifecycle критически важна. На iOS при переходе в PiP приложение получает уведомление willStart, где нужно скрыть UI и освободить память. На Android onPictureInPictureModeChanged вызывается при входе/выходе из PiP. При неверной обработке lifecycle система может выгрузить приложение из памяти, прервав воспроизведение.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также