логотип PurpleSchool
логотип PurpleSchool

Интеграция видео плеера в приложение на React Native

Автор

Олег Марков

Введение

Видеоконтент играет ключевую роль в мобильных приложениях: он делает обучение более наглядным, добавляет интерактивности и помогает держать пользователей на платформе дольше. В React Native вы можете без особых сложностей добавить современный видео-плеер — для этого достаточно использовать готовые библиотеки, которые отлично дружат с кроссплатформенной архитектурой фреймворка.

В этой статье я расскажу, как интегрировать видео-плеер в приложение на React Native, покажу, как подключить одну из самых популярных библиотек, продемонстрирую примеры кода, объясню, как настраивать и расширять функциональность плеера, а также подскажу, как обрабатывать частые ошибки. Всё будет разложено по полочкам для вашего удобства.

Выбор библиотеки видео-плеера для React Native

Для реализации функционального и кроссплатформенного видео-плеера чаще всего используют библиотеку react-native-video. Она удобна, поддерживает как Android, так и iOS, позволяет воспроизводить локальные и потоковые видеофайлы, предоставляет гибкие настройки и хорошо документирована.

Почему именно react-native-video?

  • Поддерживает HLS, DASH, mp4, mkv и другие популярные форматы
  • Позволяет проигрывать видео из интернета и из локального хранилища приложения
  • Дает возможность легко управлять воспроизведением (паузой, перемоткой, изменением громкости и скоростью)
  • Позволяет кастомизировать интерфейс плеера

Есть и альтернативы: например, expo-av (если используете Expo), но именно react-native-video считается более гибкой и функциональной при необходимости детальной настройки.

Интеграция видео-плеера в React Native приложение требует знания различных библиотек, кодеков и протоколов. Важно уметь настраивать плеер, обрабатывать события, обеспечивать поддержку различных форматов и оптимизировать воспроизведение видео для разных устройств и сетевых условий. Может потребоваться понимание работы с нативными модулями. Если вы хотите детальнее погрузиться в интеграцию видео-плеера и другие нативные возможности в React Native, — приходите на наш большой курс React Native и Expo Router. На курсе 184 уроков и 11 упражнений, AI-тренажеры для безлимитной практики с кодом и задачами 24/7, решение задач с живым ревью наставника, еженедельные встречи с менторами.

Установка и настройка библиотеки

Установка react-native-video

Сначала давайте установим зависимость в ваш проект. Если вы используете npm, выполните:

npm install react-native-video

Используете yarn? Тогда так:

yarn add react-native-video

Линковка модулей (если не используете автолинковку)

В последних версиях React Native ошибка с запуском из-за не залинкованных модулей маловероятна, но если ваш проект старый (до 0.60), то после установки выполните линковку:

react-native link react-native-video

iOS: обновление Podfile

Если вы разрабатываете под iOS, не забудьте сделать следующее в папке ios:

cd ios
pod install
cd ..

Базовый пример интеграции видео-плеера

Покажу вам простой способ вставки видео-плеера в экран вашего приложения.

import React from 'react';
import { View, StyleSheet } from 'react-native';
import Video from 'react-native-video';

const BasicVideoPlayer = () => {
  // Урл видео - можно заменить на ваш собственный
  const videoUrl = 'https://www.w3schools.com/html/mov_bbb.mp4';

  return (
    <View style={styles.container}>
      <Video
        source={{ uri: videoUrl }}    // Ссылка на видео-файл
        style={styles.video}
        controls={true}                // Показывать стандартные элементы управления
        resizeMode="contain"           // Как масштабировать видео
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'black',         // Можно указать свой фон
    justifyContent: 'center',
    alignItems: 'center',
  },
  video: {
    width: '100%',
    aspectRatio: 16 / 9,              // Пропорция видео
  },
});

export default BasicVideoPlayer;

Что происходит в этом примере:

  • Мы импортируем сам видеокомпонент.
  • Передаем в проп source объект с uri — исходное видео берётся из указанного URL.
  • Через проп controls={true} включается отображение стандартных элементов управления: play/stop/seek/volume.
  • С помощью свойства resizeMode можно управлять тем, как видео заполняет свой блок.
  • Задаём стили через StyleSheet — для удобства и правильной пропорции.

Расширенные функции и методы video-плеера

Простой пример — это здорово, но часто требуется больше контроля над видео. Например, обработка событий (когда видео проигралось до конца, когда появилась ошибка, когда изменилась позиция и т.д.), добавление своих кнопок, динамическое управление проигрыванием.

Кастомизация и события

Покажу пример, где мы реагируем на события проигрывания и отображаем, сколько секунд уже прошло с начала.

import React, { useRef, useState } from 'react';
import { View, Text, StyleSheet, Button } from 'react-native';
import Video from 'react-native-video';

const CustomVideoPlayer = () => {
  const videoRef = useRef(null);
  const [currentTime, setCurrentTime] = useState(0);
  const [paused, setPaused] = useState(false);

  // Функция вызывается, когда проигрывание идет - обновляем позицию в state
  const handleProgress = (data) => {
    setCurrentTime(data.currentTime);
  };

  // Функция вызывается, когда видео закончило проигрываться
  const handleEnd = () => {
    setPaused(true); // Ставим на паузу по окончанию
  };

  return (
    <View style={styles.container}>
      <Video
        ref={videoRef}
        source={{ uri: 'https://www.w3schools.com/html/mov_bbb.mp4' }}
        style={styles.video}
        controls={true}
        paused={paused}
        onProgress={handleProgress} // Следим за текущим временем
        onEnd={handleEnd}           // Срабатывает в конце воспроизведения
        resizeMode="contain"
      />
      <Text style={styles.timeText}>
        Текущее время: {currentTime.toFixed(1)} сек.
      </Text>
      <Button
        title={paused ? "Воспроизвести" : "Пауза"}
        onPress={() => setPaused(!paused)}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#222' },
  video: { width: 320, height: 180, backgroundColor: '#000' },
  timeText: { color: '#fff', marginTop: 12 }
});

export default CustomVideoPlayer;

Здесь вы видите:

  • Использование событий onProgress, чтобы получать время воспроизведения.
  • Использование onEnd, чтобы понять, когда видео закончилось.
  • Управление состоянием paused через кнопку.

Управление через ref

Иногда нужно программно останавливать, запускать или перематывать видео. Библиотека предоставляет ref и методы типа seek(time) — давайте посмотрим, как этим пользоваться.

// Внутри компонента:
const videoRef = useRef(null);

// ...в рендере:
<Video
  ref={videoRef}
/>

// Где-нибудь в функции обработчике:
const seekToMiddle = () => {
  // Перемотка примерно на середину видео (например, 30 секунда)
  videoRef.current.seek(30); // Секунды
};

Это полезно, например, для создания "Перейти к началу"/"Пропустить интро" и прочих кастомных функций.

Пользовательский интерфейс управления

Стандартные controls — простое решение. Если вам нужен уникальный интерфейс (например, крупная кнопка "Play" или собственные таймлайны) — controls можно отключить и создать собственные элементы UI.

Смотрите, как это реализовано:

<Video
  controls={false}
  // ...остальные пропсы
/>
<Button title="Play" onPress={() => setPaused(false)} />
<Button title="Pause" onPress={() => setPaused(true)} />

Для управления звуком, скоростью воспроизведения и другими параметрами вы просто добавляете нужные кнопки и изменяете значения пропсов плеера (например, передаете rate).

Работа с источниками видео: локальные и онлайн-файлы

Онлайновое видео (HTTP/HTTPS)

  • Передаёте ссылку на файл или поток: jsx source={{ uri: 'https://example.com/video.mp4' }}
  • Можно прямо использовать HLS (.m3u8), DASH-потоки, YouTube не поддерживается напрямую.

Локальные видеофайлы (assets и файловая система)

  • Для ресурсов, встроенных в приложение: jsx source={require('./assets/video.mp4')}
  • Для динамически скачанных файлов (находящихся в FileSystem на устройстве), указывайте путь: jsx source={{ uri: 'file:///path/to/video.mp4' }}

Особенности работы на Android и iOS

iOS

  • Если используете локальные файлы, обязательно добавьте их в настройки Xcode (Copy Bundle Resources).
  • Для потокового видео (HLS, mp4) нет дополнительных настроек.

Не забудьте добавить разрешения

В Info.plist для загрузки по http может понадобиться:

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSAllowsArbitraryLoads</key>
  <true/>
</dict>

Android

  • Проверьте, что у вас есть разрешение на доступ к интернету (android.permission.INTERNET).
  • Для локальных файлов путь должен начинаться с file:///.

Пример расширенного применения (слайдер перемотки)

Чтобы дать пользователю больше контроля, можно добавить слайдер для перемотки.

import React, { useRef, useState } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import Video from 'react-native-video';
import Slider from '@react-native-community/slider';

const SliderVideoPlayer = () => {
  const videoRef = useRef(null);
  const [currentTime, setCurrentTime] = useState(0);
  const [duration, setDuration] = useState(0);
  const [paused, setPaused] = useState(true);

  return (
    <View style={styles.container}>
      <Video
        ref={videoRef}
        source={{ uri: 'https://www.w3schools.com/html/mov_bbb.mp4' }}
        style={styles.video}
        paused={paused}
        resizeMode="contain"
        onProgress={data => setCurrentTime(data.currentTime)}
        onLoad={data => setDuration(data.duration)}
      />
      <Slider
        style={{ width: 240, height: 40 }}
        minimumValue={0}
        maximumValue={duration}
        value={currentTime}
        onValueChange={value => videoRef.current.seek(value)}
      />
      <Text style={styles.time}>{Math.floor(currentTime)} / {Math.floor(duration)} сек.</Text>
      <Text style={styles.button} onPress={() => setPaused(!paused)}>
        {paused ? '▶️ Play' : '⏸ Pause'}
      </Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: { flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: '#1e1e1e' },
  video: { width: 320, height: 180, backgroundColor: '#000' },
  time: { color: 'white', marginTop: 8 },
  button: { color: '#49b', padding: 10, marginTop: 10, fontSize: 18 }
});

export default SliderVideoPlayer;

Здесь используются:

  • Слайдер для перемотки по текущему времени видео
  • Получение полной длительности и текущего положения
  • Кнопка Play/Pause — весь UI простой и понятный

Обработка ошибок и советы по стабильной работе

  • Используйте событие onError чтобы поймать неудачные попытки проигрывания (например, когда файл не загружен):
<Video
  onError={e => {
    console.warn("Ошибка видео:", e);
    // Можно показать пользователю сообщение
  }}
/>
  • Проверьте, доступно ли у пользователя подключение к интернету, если источник видео — онлайн.
  • Для тяжелых видео рекомендуется настраивать буферизацию через параметры или показывать индикаторы загрузки.
  • При необходимости оптимизации трафика — отдавайте оптимизированные для мобил устройств видео-форматы (например, h264 с низким битрейтом).

Интеграция в сложные проекты

  • Для сложных интерфейсов интеграцию плеера лучше оборачивать в собственный компонент.
  • Старайтесь держать состояние управления видео (paused, position) в родительском компоненте или в контексте.
  • Используйте кастомные иконки и анимации, когда это требуется дизайном.

Поддержка фонового воспроизведения и PiP (картинка в картинке)

react-native-video частично поддерживает фоновое воспроизведение и режим "картинка в картинке". Для iOS достаточно правильно настроить проект (Background Modes>Audio), для Android могут потребоваться дополнительные настройки AndroidManifest и службы.

  • Для поддержки фонового воспроизведения обратите внимание на документацию по Background Modes для каждой платформы.
  • PiP на Android поддерживается только с API 26 и выше.

Добавление видеоплеера не должно вызывать сложностей, если правильно понимать все шаги. Не стоит забывать, что создание сложных приложений требует понимания многих аспектов, а не только интеграции видеоплеера. На нашем курсе React Native и Expo Router вы найдете все необходимые знания для освоения React Native разработки. В первых 3 модулях уже доступно бесплатное содержание — начните погружаться в мир React Native прямо сегодня.

Частозадаваемые технические вопросы по теме статьи и ответы на них

Как добавить подзаголовки (субтитры) к видео?

Добавьте проп textTracks к компоненту Video:

<Video
  textTracks={[
    {
      title: "English CC",
      language: "en",
      type: TextTrackType.VTT,
      uri: "https://www.example.com/subs_en.vtt"
    }
  ]}
  selectedTextTrack={{type: "index", value: 0}}
/>

Не забудьте импортировать TextTrackType из библиотеки.

Почему не работает локальное видео на Android?

Проверьте, что вы используете путь с префиксом file:/// и у файла есть права на чтение. Проверьте разрешения на чтение файлов в AndroidManifest.

Как сделать видео в full screen при нажатии на кнопку?

Контролируйте prop fullscreen:

<Video
  fullscreen={isFullScreen}
  // остальные пропсы
/>

Некоторые версии требуют ручной обработки через сторонние библиотеки или создание навигационного экрана без статуса/титулбара с Video на весь экран.

Можно ли стримить видео из YouTube?

На данный момент react-native-video не поддерживает прямое воспроизведение видео с YouTube из-за ограничений API и форматов. Используйте либо WebView, либо отдельные библиотеки для поддержки YouTube, такие как react-native-youtube-iframe.

Как управлять буферизацией видео?

Используйте события onBuffer и пропы, связанные с буферизацией (например, bufferConfig). Показывайте лоадер, когда идет буферизация:

<Video
  onBuffer={({ isBuffering }) => setBuffering(isBuffering)}
/>

И рендерьте индикатор загрузки, пока буферизация не закончится.

Стрелочка влевоНастройка и использование input и textinput в React NativeИспользование выпадающих списков в React NativeСтрелочка вправо

Постройте личный план изучения React-native до уровня Middle — бесплатно!

React-native — часть карты развития Mobile

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Бесплатные лекции

Все гайды по React-native

Работа со ScrollView в React NativeРабота с видео в React NativeКак реализовать аудиоплеер на React NativeНастройка и использование input и textinput в React NativeИнтеграция видео плеера в приложение на React NativeИспользование выпадающих списков в React NativeСоздание и настройка native module на React NativeКак создать модальные окна в React NativeРабота с изображениями в React NativeОтображение списков данных в React NativeГайд по файловой системе в React NativeИнтеграция камеры в приложение на React NativeСоздание интерактивных кнопок в React Native
Как использовать векторные иконки в React NativeСоздание и использование tabs в React Native5 популярных библиотек UI компонентов React NativeРуководство по стилизации компонентов в React NativeОптимизация переходов между экранами в React NativeАдаптация safe area context на React NativeОбзор библиотек для навигации в React NativeСоздание сложных анимаций (reanimated) на React NativeИспользование библиотеки стилей Paper в React NativeРуководство по navigation в React NativeОптимизация отображения списков в React NativeКак реализовать linking на React NativeГайд по UI-китам для React NativeГде искать elements для приложения на React NativeРабота с цветами в React Native
Открыть базу знаний

Лучшие курсы по теме

изображение курса

React Native и Expo Router

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Основы JavaScript

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий