Использовали Vimeo для хостинга товарных видео (9000 видео, 3 тб) для размещения на собственных сайтах, но из-за частичных блокировок Cloudflare в России, с середины прошлого года Vimeo работал с перебоями.

Цель - сделать хостинг видео для товаров на собственной платформе, чтобы не зависеть от сторонних поставщиков.

Что было важно:

  • отсутствие рекламы для пользователей;

  • отсутствие ошибочных блокировок модераторами или алгоритмами;

  • реализация в отраслевые стандартах видеохостингов;

  • желательно, гео распределение для ускорения отдачи видео, т.к. многие заходят "из" EU / US.

Имеющиеся социальные платформы ВКвидео / Rutube не подходили, из-за наличия рекламы, потенциальной модерации, меняющихся правил и отсутствия глобального CDN. Видеохостинг Yandex Cloud Video рассматривали, но у него также не было глобального CDN, а теперь ещё добавились риски потери данных.

Основные требования

Нам был нужен видеоплеер как у Vimeo и YouTube к которому пользователи привыкли:

  • Автоматический выбор качества видео в зависимости от скорости интернета пользователя;

  • Ручное переключение качества;

  • Мгновенный старт видео, не требующий ожидания его полной загрузки;

  • Мгновенный переход при проматывании к нужной точке;

  • Возможность во время проигрывания водить курсором/пальцем по таймлайну и видеть превью;

  • Разметка по тайм кодам (не обязательно, но хотелось).

В плане управления:

  • интерфейс администрирования с возможностью загрузить видео;

  • менять название и описание - для редакторов;

  • наличие API - для автоматизации.

Поиск решения

При изучении вопроса выяснил, что для проигрывания видео на сайте, так же как это работало у Vimeo, недостаточно разместить MP4 файл на сервере и вставить стандартный HTML-плеер.

С каждым видео файлом нужно совершить ряд действий:

  • Сконвертировать в несколько разрешений (360 / 480 / 720 / 1080 / 1440 / 2160);

  • Перевести в формат Fragmented MP4 - видео нарезается на небольшие фрагменты, к которым плеер обращается по мере воспроизведения, не загружая файл целиком;

  • Сформировать HLS-плейлисты - в них хранится информация о тайминге фрагментов, которую использует плеер;

  • Сгенерировать Storyboard - изображение с кадрами из всего видео, которое пользователь видит, проводя пальцем по таймлайну, с разметкой по таймингу.

Эти все действия на бэке совершал Vimeo. Реализовывать всё это самостоятельно нецелесообразно - слишком большие трудозатраты, и любая повторная конвертация с нашим объёмом будет занимать месяцы.

Помимо подготовленных файлов, нужен современный плеер, который всё это поддерживает.

Из готовых решений на глобальном рынке нашёл бесплатный open-source проект PeerTube. Существует с 2018 года, и на момент установки в прошлом году была актуальная 7 версия, сейчас уже 8.​

Продукт живой, развивающийся. Есть документация и готовые примеры с API. Разворачивается на собственном сервере (self-hosted).

В итоге для перехода на собственный видеохостинг потребуется:

  • Основной сервер (в нашем случае VDS) в RU локации;

  • Дополнительные ноды (VDS в EU и US).

  • Сервисы на сервере, отвечающие за фоновую обработку и передачу видео - обеспечивает PeerTube;

  • Современный плеер на сайте, отвечающий за воспроизведение - обеспечивает PeerTube.

Плеер с изменяемым качеством и размеченными главами
Плеер с изменяемым качеством и размеченными главами
Разметка видео по эпизодам и storyboard.
Разметка видео по эпизодам и storyboard.

Установка

Для установки требуется домен ведущий на IP сервера, в моём случае это домен 3-го уровня - peertube.[мой-домен].

На сервере ОС Ubuntu 24, PeerTube ставил на хосте без docker.

Процесс развёртывания описан подробно в документации на сайте PeerTube и сводится к 3 блокам:

  • Установка зависимостей (nodejs, postgres, redis, nginx, ffmpeg);

  • Установка самого PeerTube;

  • Настройка конфигов peertube и nginx для домена и запуск.

Тестирование

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

Всё работает и выглядит как классические видеохостинги, и при этом на собственном сервере.

После загрузки видео сразу получаем ID, например: tB1z3tSyx8YcRo2mq4ZcRs. При этом само видео будет конвертироваться дальше в фоне, как это и было у Vimeo.

Далее проверил загрузку по API, всё также стандартно и привычно как было у Vimeo.

Адреса у видео будут двух видов

  • внутри интерфейса - [мой-домен]/w/tB1z3tSyx8YcRo2mq4ZcRs

  • при встраивании на сайт - [мой-домен]/videos/embed/tB1z3tSyx8YcRo2mq4ZcRs

Встраивается на сайт стандартным образом через iframe, либо более продвинутый вариант js api:

<iframe title="Демо видео 4" width="560" height="315" src="https://[мой-домен]/videos/embed/tB1z3tSyx8YcRo2mq4ZcRs" style="border: 0px;" allow="fullscreen" sandbox="allow-same-origin allow-scripts allow-popups allow-forms"></iframe>

Данный вариант полностью закрывал все наши потребности, и позволял из коробки без собственных разработок организовать альтернативу Vimeo под нашим контролем.

Загрузка видео через интерфейс PeerTube
Загрузка видео через интерфейс PeerTube
Редактирование уже загруженного видео
Редактирование уже загруженного видео

Технические требования

Для работы платформы разработчики заявляют минимум 1 ядро + 2 Гб памяти + 20 мегабит канал. И 4 ядра + 4 Гб памяти + 1 гигабит канал для 1000 одновременных просмотров.

Под необходимую нам полосу пропускания в 60 - 80 мегабит я взял 2 ядра, 4 Гб памяти, HDD и канал 100 мегабит.

Диски целенаправленно брал более дешёвые HDD вместо SSD, т.к. это выгоднее по цене за терабайт. Теоретическая скорость HDD это 100 мегабайт в секунду, этого достаточно и для гигабитного канала.

Здесь важно отметить, воспроизведение готовых видео не потребляет значительных ресурсов. Основная сложность в конвертации, особенно первичной при переходе на платформу.

Конвертации 300 гигабайт на 2 ядрах занимает 3 недели. Соответственно 3 Тб уже 30 недель.

Помогла встроенная опция конвертации на внешних серверах (runners). Я временно сделал 2 сервера по 20 ядер на каждом и PeerTube отправлял все загружаемые видео на них, и готовые складывал локально.

В дальнейшем внешние сервера я удалил. Для регулярных конвертаций нам двух ядер достаточно. Даже когда они полностью загружены, пользователи легко смотрят имеющиеся готовые видео.

Общий вид главной страницы PeerTube
Общий вид главной страницы PeerTube

Гео распределение

Для нас важно было иметь целостный сервер со всеми видео в RU локации под своим контролем, а гео распределение, как дополнительная опция.

В этой связи какие либо варианты с гео распределённым S3 хранилищем не рассматривал, и судя повсему надёжных вариантов поддерживающих RU+Global не существует.

Отмечу, что PeerTube поддерживает хранение готовых видео файлов на внешнем S3 хранилище.

Потенциально можно использовать self-hosted S3 сервис Garage, который позволяет организовать гео распределённое хранение файлов на собственных серверах, но требуется больше нод и схема усложняется под использование GeoDNS.

Нам хотелось максимально просто раскидать файлы на 2-3 дополнительные локации и в зависимости от IP через nginx отдавать видео из EU или US.

Реализация

На основном RU сервере дополнительно установил:

  • модуль MaxMind GeoIP2 для nginx;

  • сами базы GeoIP;

  • утилита от MaxMind для автоматического обновления баз.

Базы GeoIP2 Lite бесплатные, но нужно зарегистрироваться и получить API ключ у MaxMind. Эти все процедуры стандартные и описаны в документации MaxMind.

На нодах из софта требуется только nginx с конфигами от основного с изменёнными доменами:

  • peertube-eu.[мой-домен]

  • peertube-us.[мой-домен]

Синхронизация видео на ноды

С основного RU сервера через rsync синхронизирую полностью папку PeerTube /var/www/peertube/ на EU и US ноды.

Синхронизацию делаю несколько раз в сутки. При необходимости можно сделать в момент загрузки видео, но для этого нужно писать nodejs plugin для peertube, которым ловит ивент загрузки видео. Нам данное усложнение не требовалось.

Определение страны по IP через nginx

На основном RU сервере по IP пользователя определяю страну, через установленную ранее базу GeoIP:

geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
        auto_reload 24h;

        $geoip_country_code country iso_code;
}

По определённой стране делаю префикс для ноды:

map $geoip_country_code $peertube_node {
        default "";
        "NL" "-eu";
        "ES" "-eu";
        "DE" "-eu";
        "FR" "-eu";
        "IT" "-eu";
        "FI" "-eu";
        "US" "-us";
}

И в случае EU или US отдаю видео с дополнительных VPS.

Для этого через sub_filter в конфиге nginx peertube (в секции Application) добавляю префикс к домену:

##
# Application
## 

sub_filter_types application/javascript application/json text/css;
sub_filter 'peertube.[мой-домен]/static/streaming-playlists/' 'peertube$peertube_node.[мой-домен]/static/streaming-playlists/';  

Схема с sub_filter позволяет заменять весь вывод js/json, и не требует изменения скриптов PeerTube и соответственно дальнейшие обновления можно будет легко устанавливать, всё будет работать.

В результате

PeerTube и вся логика работает на RU сервере, а непосредственно тяжёлые файлы с видео для посетителей из EU и US отдаются в фоне с отдельных нод напрямую, минуя RU.

Дополнительные опции

Отмечу некоторые опции, которыми сам не пользовался, но считаю, что они заслуживают внимания.

1. Возможность подключить S3 хранилище.

С её помощью можно изменить логику хранения и делать конвертацию на основном быстром сервере с небольшим диском. При этом готовые видео складывать в более дешёвое S3 хранилище. Это дополнительно снимает ограничения по объёму диска.

2. Автоматическое создание AI субтитров.

PeerTube из коробки умеет генерировать субтитры через встроенный движок на базе Whisper - open-source модели от OpenAI, которая работает локально на сервере без каких-либо API ключей и внешних запросов.

Задача ресурсоёмкая - как и конвертация и она также может выполняться на внешних серверах (runners с GPU).

3. Встроенная видеостудия.

Позволяет редактировать видео прямо в интерфейсе, добавлять intro / outro, логотипы, вырезать фрагменты.

4. Возможность отделить аудио дорожку от видео файлов при конвертации.

Это сокращает размер, тк не нужно встраивать аудио во всех разрешения.

5. Описание видео поддерживает markdown разметку.

Можно расставить таймкоды, ссылки и прочее.

Комментарии (3)


  1. musicman3
    30.10.2026 12:13

    Конвертацию видео я так понимаю может делать видеокарта с встроенными инструкциями, чтобы не отдавать на сторону? Типа QuickSync Video в Intel (встройки и дискрет) и NVENC от Nvidia? Если так, то тогда нагрузки вообще не будет на процессор. Также можно и локальную LLM на нее запустить для субтитров.


    1. andreypr207 Автор
      30.10.2026 12:13

      peertube использует ffmpeg и профиль libx264, которые кодирует на CPU.

      для использования GPU нужно установить plugin сторонний, позволяющий включить профиль для GPU, h264_nvenc (NVIDIA), h264_vaapi или h264_qsv (Intel/AMD)


      1. musicman3
        30.10.2026 12:13

        Значит проблема конвертации решается локально (без стороннего сервиса) без нагрузки на CPU, встроенными инструкциями процессора (точнее его видеокарты, если она там есть), либо внешней видеокарты с нужными хардварными кодеками, если конечно это не десятки-сотни видео в минуту от разных пользователей. До десятка одновременных потоков нормальная встройка потянет в качестве 1080.

        264 кодек вообще много где встроен на уровне железа в Intel и AMD процы. Если на сервере Xeon, то в большинстве случаев там встройки не было, хотя есть версии типа E3-12xx где она есть. Поэтому на процах без встройки нужно ставить дискретную графику.

        Мне так повезло, что у меня Xeon E3-1225 V5 со встроенной графикой Intel HD Graphics P530 и отдельная видеокарта Nvidia. Так для конвертации видео в Jellyfin и Nextcloud я удачно юзаю встроенную графику, а для LLM использую Nvidia, тем самым не сжирая ресурсы видеокарты и не выгружая под завязку загруженную память карты в CUDA (конвертор жрет немного памяти карты для своих нужд, а для LLM обычно все отведено впритык).