- Примеры реализации видеосервисов на основе ReactPlayer-
1. Обзор проекта
Данный случай представляет собой проект, осуществляемый для перехода от существующей системы пользовательских руководств на базе PDF к сервису на основе видеоконтента. В существующей системе пользователь нажимал кнопку руководства, и фронтенд напрямую получал доступ к AWS S3 для загрузки PDF-файла. Этот подход был прост в реализации, но имел ограничения: пользователям было трудно одновременно проверять экран работы и руководство, а также сложно было интуитивно передавать сложные процедуры.
Клиент требовал функции PIP (картинка в картинке), чтобы пользователи могли одновременно просматривать руководство в видеоролике, сохраняя открытым рабочий экран. В то же время необходимо было заблокировать прямой доступ к AWS S3 по политике безопасности, и существовали ограничения на использование чувствительной аутентификационной информации в URL-параметрах. Таким образом, ключевой аспект данного проекта заключался не только в простой реализации функции воспроизведения видео, но и в проектировании структуры аутентификации и потоковой передачи, которая удовлетворяет требованиям безопасности и основана на браузерном воспроизведении видео.
2. Выбор технологий и направление проектирования
В области Frontend была внедрена библиотека видеоплеера на основе React под названием ReactPlayer. ReactPlayer работает на основе тега HTML5 video, обладает высокой совместимостью с окружением React и имеет преимущества, такие как относительно простое управление состоянием воспроизведения и функция PIP.
Однако ReactPlayer использует способ запроса тега video, поэтому запрос видеофайлов выполняется в основном методом GET. Поскольку невозможно передать учетные данные в теле запроса или свободно настраивать заголовок, как это делается в обычных API вызовах, необходимо было разделить процесс аутентификации и фактический запрос на воспроизведение видео.
Пример кода 1. Пример вызова ReactPlayer
|
|
Данный пример показывает структуру, при которой ReactPlayer воспроизводит видео на основе конечной точки (endpoint), полученной от сервера. Учетные данные не включены в URL, а обрабатываются путем передачи временного токена, выданного на этапе предварительной аутентификации, в Cookies.
3. Редизайн архитектуры
Существующая структура позволяла фронтенду напрямую обращаться к AWS S3. Однако при предоставлении видеоконтента поддержание такой структуры могло привести к раскрытию пути хранения, повторному использованию URL и возможному обходу контроля доступа. В связи с этим мы разделили роли сервера следующим образом.
|
Фронтенд |
Сервер A отвечает за аутентификацию пользователей, проверку прав, выдачу временных токенов и промежуточную передачу запросов на потоковую передачу. Сервер B отделен для обработки только запросов на получение фактических видеофайлов и доступа к AWS S3. Это позволяет блокировать клиентам прямой доступ к пути хранения и настраивать так, чтобы все запросы на видео проходили проверку аутентификации сервера.
4. Процесс аутентификации и воспроизведения
Когда пользователь нажимает кнопку мануала, сначала не вызывается видеоплеер, а отправляется запрос API проверки пользователя на Сервер A. После завершения проверки Сервер A выдает конечную точку для воспроизведения видео и временный токен с ограниченным сроком действия. Временный токен сохраняется в Cookie браузера и передается вместе с вызовом конечной точки видео в ReactPlayer.
Пример кода 2. Запрос информации о воспроизведении видео
|
const openManualVideo = async (manualId: string) => { |
Этот код является примером того, как отправить запрос на воспроизведение видеопотока, когда нажата кнопка «Руководство». На этом этапе сервер проверяет права пользователя и отвечает, сохраняя временный токен в Cookie.
Пример кода 3. Пример выдачи временного токена Cookie
|
ResponseCookie cookie = ResponseCookie.from("VIDEO_ACCESS_TOKEN", token) |
В Cookie применены параметры HttpOnly, Secure и SameSite, чтобы ограничить доступ скриптов и ненужные внешние передачи. Кроме того, были указаны path и maxAge, чтобы они использовались только для запросов видео.
5. Обработка потокового вещания
Потоковая передача видео, в отличие от обычного скачивания файлов, непрерывно передает большие объемы данных, и при перемещении пользовательской позиции воспроизведения могут возникать частичные запросы на основе заголовка Range. Поэтому Сервер A должен передать заголовок Range клиента Серверу B, а также передать статус ответа и основные заголовки от Сервер B обратно клиенту.
Пример кода 4. Стриминг на основе заголовка Range
|
@GetMapping("/api/videos/{manualId}/stream") |
Ключевым моментом этого метода является то, что он не загружает весь файл в память, как в случае с bodyToMono(Resource.class) или bodyToMono(byte[].class). Используя bodyToFlux(DataBuffer.class), вы можете передавать видеоданные порциями (chunk), что подходит для обработки больших объемов видео.
Пример кода 5. Основная фильтрация заголовков потоковой передачи
|
private boolean isStreamingHeader(String name) { |
Заголовки, такие как Content-Range, Accept-Ranges и Content-Length, необходимы браузеру для определения длины видео и диапазона частичного ответа. Особенно важно сохранять эти заголовки для обеспечения функции навигации и стабильного воспроизведения.
6. Результаты и эффекты
Результаты реализации пользователи смогли сразу воспроизводить видео в браузере и одновременно использовать рабочий экран и видеоруководство через функцию PIP. Кроме того, было возможно удовлетворить требования безопасности, исключив прямой доступ к AWS S3 и применив серверный контроль доступа.
• Удаление прямого экспонирования AWS S3
• Удаление передачи конфиденциальной информации на основе URL
• Разрешение на доступ к видео endpoint после проверки пользователя
• Ограниченный контроль доступа на основе временных токенов
• Поддержка воспроизведения и навигации видео на основе заголовка диапазона
7. Заключение
В этом примере я не только добавил видеоплеер, но также получил опыт в проектировании с учетом работы ReactPlayer и тега HTML5 video, политики безопасности клиента, разделения ролей между серверами и способов обработки потоковой передачи. Разделив процесс аутентификации и воспроизведения и четко разделив ответственность между сервером A и сервером B, мы смогли одновременно обеспечить пользовательский опыт и безопасность.
Особенно в рабочей среде я почувствовал, что важно понимать не только реализацию функциональных возможностей, но и ограничения политики безопасности и работы браузера. Этот проект подтвердил, что для стабильного предоставления сервисов на основе видео необходимо учитывать структуры аутентификации, поток данных, обработку заголовков потоковой передачи и операционные политики безопасности.
NZ