Видеоплеер — Обзор функциональности
Документ описывает возможности встроенного видеоплеера, построенного на базе better_player (обёртка над Flutter video_player) с интеграцией audio_service для фонового воспроизведения.
Основное воспроизведение
| Функция | Описание |
|---|---|
| HLS-адаптивный стриминг | Сетевые источники используют ASMS-треки с адаптивным переключением битрейта. |
| Локальное (офлайн) воспроизведение | PlayableSource.local позволяет воспроизводить загруженные файлы с диска. |
| Фоновая аудиосессия | VideoBackgroundHandler наследует BaseAudioHandler; интегрируется с AudioService и AudioSession для управления воспроизведением в фоне и с экрана блокировки. |
| Управление через уведомления Android | Элементы управления (воспроизведение, пауза, перемотка, пропуск) отображаются в канале уведомлений Android. Компактные кнопки адаптируются в зависимости от позиции в очереди. |
| Автовозобновление прогресса | При открытии видео плеер перематывает к последней сохранённой позиции (прогресс сохраняется для каждого медиа-элемента). Видео, просмотренные на ≥ 97%, начинаются сначала. |
| Обработка ошибок и повтор | При сбое воспроизведения отображается VideoPlaybackFailedWidget с кнопкой повтора или закрытия в зависимости от наличия сети. |
Управление воспроизведением
| Элемент управления | Детали |
|---|---|
| Воспроизведение / Пауза | Центральная кнопка с индикатором загрузки при буферизации. |
| Перемотка вперёд / назад (кнопки) | Выделенные кнопки перемотки в оверлее управления. |
| Двойной тап для перемотки | Двойное нажатие на левую или правую половину области видео для перемотки без открытия оверлея (DoubleTapRewindWidget). |
| Полоса прогресса | Кастомная перетаскиваемая полоса прогресса в стиле Cupertino с индикатором буферизации. |
| Переход к следующему видео | Кнопка «вперёд» отображается при наличии следующего непросмотренного видео в плейлисте. Уже завершённые видео пропускаются. |
Плейлист и очередь
| Функция | Описание |
|---|---|
| Плейлист курса | Загружается для каждого курса; отображается в нижней интерактивной панели. Поддерживает выбор видео по индексу. |
| Плейлист избранного | Отдельный плейлист избранного, загружаемый параллельно с основной очередью. |
| Ленивая подгрузка следующей страницы | При приближении к концу текущего плейлиста следующая порция элементов загружается автоматически (getNextPlaylist). |
| Автовоспроизведение | Переключатель в настройках. При включении следующее видео запускается автоматически после завершения текущего. При отключении вместо этого срабатывает интерактивная панель или экзаменационный флоу. |
Настройки (с сохранением)
Все настройки сохраняются через PlayerSettingsStorage (SharedPreferences) и восстанавливаются при следующем сеансе.
| Настройка | Значения |
|---|---|
| Скорость воспроизведения | 0.75×, 1× (Обычная), 1.25×, 1.5×, 1.75×, 2× |
| Качество видео | Авто или конкретное разрешение (например, 720p, 1080p) из ASMS-треков. |
| Субтитры | Вкл / Выкл — управляет отображением субтитров. |
| Автовоспроизведение | Вкл / Выкл — управляет автоматическим переходом к следующему видео. |
Субтитры
- Субтитровые дорожки загружаются из HLS-манифеста (
useAsmsSubtitles: true). - При инициализации плеер автоматически выбирает субтитры, соответствующие локали приложения (
_setupSubtitlesByLocale). - Субтитры отображаются в кастомном оверлее (
VideoPlayerSubtitlesPresenter), который скрывается при перетаскивании полосы прогресса и когда видны элементы управления. - Видимость субтитров переключается пользователем и сохраняется между сеансами.
Картинка в картинке (PiP)
- Поддерживается на iOS (нативный AVPlayer PiP) и Android (
android_pip). - Кнопка PiP в верхних элементах управления плеера.
- При входе в PiP: полноэкранный плеер скрывается, интерактивные панели закрываются, навигация возвращается к корневому маршруту.
- При выходе из PiP: полноэкранный плеер восстанавливается с оверлеем, воспроизведение продолжается.
- PiP разрешён для каждого медиа индивидуально через
PlayableMedia.allowPIP.
AirPlay (iOS)
- Кнопка выбора маршрута AirPlay отображается только на iOS (
flutter_to_airplay). - Активная трансляция обозначается жёлтым цветом иконки.
- При выходе из PiP во время AirPlay-трансляции воспроизведение автоматически возобновляется на устройстве AirPlay.
CurrentRouteNotifierотслеживает, транслируется ли видео на внешний дисплей.
Масштабирование щипком (интерактивное видео)
InteractiveVideoоборачивает плеер вInteractiveViewerс поддержкой масштабирования отminScale(вписать по размеру) до 4×.- Масштаб возвращается к вписыванию или заполнению с анимированными переходами и тактильной обратной связью.
- При первом использовании показывается Lottie-анимация обучения масштабированию, которая автоматически исчезает через 6 секунд.
- Изменение ориентации сбрасывает уровень масштабирования.
Закладки
| Функция | Описание |
|---|---|
| Создание закладки | Кнопка закладки в верхних элементах управления открывает AddBookmarkDialog с текстовым полем ввода. Воспроизведение приостанавливается, пока диалог открыт. |
| Закладки на полосе прогресса | Созданные закладки отображаются жёлтыми маркерами на полосе прогресса (BookmarksOnProgressBar). |
| Уведомление о создании закладки | После сохранения закладки отображается снэкбар с подтверждением. |
| Зависимость от сети | Кнопка закладки отображается только при наличии сетевого подключения. |
Таймер сна
| Функция | Описание |
|---|---|
| Таймер по времени | Пользователь выбирает часы и минуты через колёсный пикер. По умолчанию: 15 минут. |
| Режим «до конца видео» | Переключатель для автоматической остановки воспроизведения по окончании текущего видео. |
| Экран обратного отсчёта | Активный таймер отображает нижний лист с обратным отсчётом. |
| Состояние таймера при пропуске | Если таймер в режиме «до конца видео» и пользователь переключает видео, таймер перезапускается для нового видео. |
Аннотации видео
- Аннотации загружаются для каждого видео через
AnnotationsBlocпосле инициализации видео. - Типы аннотаций определяются
VideoAnnotationTypeIdи рендерятся черезAnnotationPresenterFactory. - Система поддерживает различные типы аннотаций, используемые в лекциях:
- Аннотации лекций
- Навигация к следующей лекции
- Навигация к следующему саммари
- Запросы обратной связи / оценки курса
- Аннотации-ссылки
- Аннотации-лайки
- Аннотации с формами
Интерактивная панель и интеграция с экзаменами
| Функция | Описание |
|---|---|
| Оверлей интерактивной панели | Выдвижная панель (PlayerInteractiveBoxWidget), которая может отображать: плейлист, избранное или контент экзамена. |
| Запуск экзамена из плеера | Когда автовоспроизведение выключено и видео заканчивается, плеер проверяет доступность экзамена и может перенаправить на экзаменационный флоу. |
| Переход к симулятору | Если у видео есть возможность обратной связи (canAddFeedback), плеер перенаправляет на страницу симулятора при закрытии. |
| Материалы курса | В нижних элементах управления отображается кнопка материалов — разблокирована после прохождения экзамена, заблокирована в остальных случаях. |
| Оценка курса | Кубит оценки курса, запускаемый в рамках интерактивной панели. |
Отслеживание вовлечённости и аналитика
SummaryEngagementDispatcherотслеживает время просмотра каждого видео с помощью секундомера.- Отправляет
VideoPlayerEngagementEventкаждые 5 секунд во время воспроизведения. - При смене медиа или закрытии плеера отправляет
VideoPlayerEngagementCompletedEventс общей, максимальной за саммари и сегодняшней продолжительностью. VideoPlayerSummaryWatchThresholdEventсрабатывает при пересечении настраиваемого порога прогресса просмотра (из remote config).WatchTimeControllerотслеживает накопительное время просмотра, сбрасывается при переключении видео.
Ориентация и полноэкранный режим
| Функция | Описание |
|---|---|
| Автоориентация | Плеер устанавливает ориентацию устройства на основе соотношения сторон видео при открытии. |
| Развернуть / Свернуть | Кнопка переключения полноэкранного режима в правом нижнем углу элементов управления. |
| Ландшафтный поворот | На мобильных устройствах (не планшетах) контент приложения поворачивается, когда плеер в ландшафтном режиме. |
| Системный UI | Системные оверлеи (статус-бар, панель навигации) скрываются, пока плеер виден, и восстанавливаются при закрытии. |
| Блокировка ориентации при открытых листах | Нижние листы (таймер, настройки) временно блокируют ориентацию для предотвращения проблем с вёрсткой. |
Плееры трейлеров
Отдельные облегчённые реализации плееров для трейлеров:
| Расположение | Описание |
|---|---|
| Трейлер на экране курса | Встроенный трейлер на странице детальной информации о курсе с кастомными элементами управления. |
| Трейлер главной подборки | Плеер трейлера в главной подборке на домашнем экране. |
| Управление трейлером | Упрощённые элементы управления с поддержкой субтитров (TrailerPlayerControls, TrailerSubtitlesPresenter). |
Фоновая работа и жизненный цикл
| Функция | Описание |
|---|---|
| Блокировка экрана | Экран остаётся активным во время воспроизведения видео (WakeLockController). |
| Обработка аудиопрерываний | InterruptionListener ставит на паузу и возобновляет воспроизведение при аудиопрерываниях (звонки, другие приложения). |
| Учёт жизненного цикла | Обрабатывает изменения AppLifecycleState — восстанавливает ориентацию PiP при возобновлении. |
| Очистка кэша | Кэш плеера очищается при переключении видео и при закрытии плеера. |
Архитектура (обзор)
AfiVideoPlayerController (координатор)
├── VideoBackgroundHandler (движок воспроизведения + AudioService)
│ └── BetterPlayerController
├── VideoPlayerOverlayController (видимость элементов управления и автоскрытие)
├── VideoPlayerProgressController (перемотка и перетаскивание)
├── VideoPlayerLoadingController (состояние буферизации)
├── VideoPlayerVisibleController (показ / скрытие плеера)
├── VideoPlayerPipController (режим PiP)
├── VideoPlayerOrientationController (управление ориентацией)
├── VideoPlayerSubtitleController (состояние субтитров)
├── PlayerTimerCubit (таймер сна)
├── PlayerInteractiveBoxController (оверлей-панель: плейлист, избранное, экзамен)
├── PlaylistBloc + PlaylistProvider (состояние и данные плейлиста)
└── FavoritesPlaylistBloc (состояние плейлиста избранного)Виджет VideoPlayerOverlay оборачивает всё приложение как глобальный оверлей, позволяя плееру отображаться поверх всех экранов. Он объединяет экземпляр BetterPlayer, слои управления, отображение субтитров, систему аннотаций, закладки и интерактивную панель в единый координированный стек.