# Как создать архитектуру YouTube с Kafka, S3 и адаптивным стримингом

Источник: https://www.youtube.com/watch?v=FiXOaYnW64w
Канал: freeCodeCamp.org
Опубликовано: 11.06.2024

---

Эта статья основана на курсе Кирти Пурвани (Keerti Purwani), опубликованном на канале freeCodeCamp.org. В ней подробно разбирается процесс создания архитектуры видеоплатформы уровня YouTube с нуля, включая вопросы загрузки, транскодирования и адаптивного стриминга.

## 📺 Эволюция пет-проектов: почему обычные клоны больше не работают
[[JUMP:0:00]]

Современный рынок разработки ПО стал чрезвычайно конкурентным. По мнению автора курса Кирти Пурвани, создание простых веб-приложений или визуальных клонов известных сервисов больше не впечатляет работодателей [1:08]. Сегодня от инженера ожидают понимания принципов системного проектирования (High-Level Design, HLD). Данный проект — это не просто интерфейс YouTube, а полноценная распределенная система, включающая:

*   Три независимых микросервиса: Upload Service, Watch Service и Transcoder Service [0:40].
*   Инфраструктуру обмена сообщениями на базе Apache Kafka [0:54].
*   Реляционную базу данных PostgreSQL для метаданных [0:54].
*   Облачное хранилище S3 и сложные алгоритмы обработки видео [6:25].

Кирти утверждает, что весь код был написан в рамках живых сессий общей длительностью около 6 часов, где каждая строка объяснялась студентам минимум дважды [2:26].

## 🏗️ Первый этап: ядро системы и клиентская часть
[[JUMP:4:38]]

Проектирование начинается не с архитектуры, а с реализации базовых функций. Кирти рекомендует начинающим разработчикам сначала сфокусироваться на трех столпах: загрузке (upload), просмотре (watch) и преобразовании (transcode) [4:51].

Для реализации видеоплеера на стороне клиента (Next.js) используется библиотека `react-player` [5:44]. На первом этапе система учится трем вещам:

1.  Воспроизведению любого внешнего URL с YouTube [5:58].
2.  Стримингу собственного видео и аудио пользователя (аналог функционала Zoom) [6:12].
3.  Воспроизведению файлов напрямую из публичного бакета S3 [6:39].

Затем создается **Upload Service** на Node.js [7:44]. Изначально это простейший API, который принимает файл и отправляет его в облако S3. Автор подчеркивает важность поэтапного усложнения: сначала загружается обычная PNG-картинка, затем маленькое видео, и только потом система переходит к обработке тяжелого контента [8:26].

## 🔐 Аутентификация и безопасность
[[JUMP:13:00]]

Безопасность системы реализована через протокол OAuth с использованием библиотеки **NextAuth.js** [13:26]. Выбор пал на авторизацию через Google, так как это стандарт для современных платформ.

Ключевые технические детали:

*   Логика аутентификации выполняется на серверной стороне Next.js [13:39].
*   Для настройки требуется конфигурация в Google Cloud Console [14:05].
*   Только авторизованные пользователи получают доступ к функционалу загрузки видео [14:56].

## 📨 Внедрение Apache Kafka и принципов HLD
[[JUMP:15:11]]

Когда базовый поток «клиент — сервер — S3» отлажен, Кирти вводит концепции High-Level Design. Прямая загрузка видео неэффективна, так как после получения файла система должна выполнить множество ресурсозатратных задач: фильтрацию контента на запрещенные материалы, проверку авторских прав и, самое главное, транскодирование в разные разрешения (1080p, 720p и т.д.) [15:36].

Для решения этой задачи используется паттерн **Pub-Sub** (Publisher-Subscriber) на базе Kafka [16:03]:

*   **Upload Service** выступает в роли продюсера (Producer): после завершения загрузки он отправляет сообщение в топик `transcode` [18:03].
*   **Transcoder Service** выступает в роли потребителя (Consumer): он «слушает» топик и начинает обработку видео, как только появляется новое задание [18:54].

Автор использовала облачное решение **Aiven** для развертывания Kafka и PostgreSQL, отмечая его удобство для обучения [17:51].

## 📦 Чанкинг и Multipart Upload в S3
[[JUMP:20:15]]

Загрузка 10-гигабайтного файла одним куском практически невозможна из-за ограничений сети и высокого риска сбоев. Решением является **чанкинг** — разделение видео на мелкие части (чанки) [20:27].

**Спорный момент в архитектуре:** где делить видео?
Кирти задает вопрос: делать это на бэкенде или фронтенде? По её мнению, правильный подход — чанкинг на стороне клиента [21:08]. Это позволяет отправлять части параллельно, что значительно ускоряет процесс.

Для сборки видео на стороне S3 используется механизм **Multipart Upload**, состоящий из трех этапов [27:29]:

1.  **Initiation**: Запрос на начало загрузки, получение `uploadID` [29:30].
2.  **Parts Upload**: Параллельная отправка кусков. За каждую часть S3 возвращает `eTag` (уникальный идентификатор части) [29:56].
3.  **Completion**: Отправка массива всех `eTag` и `partNumber`. После этого S3 автоматически «склеивает» видео в один файл [30:08].

## 📈 Балансировка и параллелизм
[[JUMP:37:17]]

Для оптимизации загрузки Кирти использует массив промисов в JavaScript. Вместо того чтобы ждать завершения загрузки каждого чанка по очереди (`await` внутри цикла), клиент отправляет все части сразу, а затем ожидает их завершения через `Promise.all` [37:57]. Это создает нагрузку на бэкенд, но при наличии балансировщика нагрузки (Load Balancer) позволяет достичь максимальной пропускной способности канала [38:22].

## 🗄️ Watch Service и работа с метаданными
[[JUMP:39:15]]

Когда видео оказывается в S3, данные о нем должны быть доступны для поиска и отображения. Для этого создается **Watch Service** и база данных PostgreSQL.

В качестве ORM используется **Prisma** [40:09]. Процесс выглядит так:

*   После того как S3 подтвердил сборку файла, Upload Service получает финальный URL.
*   Метаданные (название, описание, автор, ссылка на S3) записываются в БД через Prisma [42:35].
*   Watch Service предоставляет API для получения списка всех видео (`findMany`) [54:27].

Кирти упоминает технологию **Vitess**, которую YouTube использует для горизонтального масштабирования MySQL, но в рамках учебного проекта ограничивается классической PostgreSQL [12:35].

## 🔄 Адаптивный стриминг (HLS) и транскодирование
[[JUMP:59:00]]

Самая сложная часть проекта — реализация **Adaptive Bitrate Streaming**. Это технология, позволяющая видеоплееру автоматически менять качество видео (например, с 1080p на 480p) при ухудшении интернет-соединения [59:52].

Для реализации используется протокол **HLS (HTTP Live Streaming)** от Apple [1:02:56]. Суть процесса:

1.  **FFMPEG**: Программное обеспечение, которое перекодирует исходное видео в несколько разрешений (320p, 480p, 720p) одновременно [1:09:29].
2.  **Сегментация**: Каждое видео режется на 10-секундные кусочки с расширением `.ts` [1:06:52].
3.  **Манифест (`.m3u8`)**: Текстовый файл-плейлист, который содержит ссылки на все сегменты. Создается «мастер-плейлист», который указывает плееру, какие файлы соответствуют какому разрешению [1:07:58].

## 🛠️ Модель «S3 to S3»
[[JUMP:1:17:46]]

Финальная схема работы Transcoder Service выглядит так:

*   Сервис скачивает оригинал видео из S3 во временную локальную папку [1:20:21].
*   Запускает процесс транскодирования через бинарные файлы `ffmpep-static` [1:09:42].
*   Создает структуру папок с манифестами и сегментами.
*   Загружает всю структуру обратно в S3 и удаляет локальные временные копии [1:21:03].

## 🏁 Резюме архитектуры (HLD Diagram)
[[JUMP:1:21:43]]

В завершение Кирти сводит все компоненты в единую диаграмму:

1.  **Клиент (Next.js)** инициирует загрузку чанками.
2.  **Upload Service** управляет Multipart Upload в S3, пишет метаданные в **PostgreSQL** и кидает задачу в **Kafka**.
3.  **Transcoder Service** забирает задачу, скачивает видео, дробит его на сегменты для разных разрешений через **FFMPEG** и возвращает результат в S3.
4.  **Watch Service** отдает клиенту ссылки на HLS-манифесты из базы данных.

По словам автора, реализация такой системы дает инженеру «не просто проект для портфолио, а глубокое понимание того, как работают высоконагруженные платформы в реальности» [1:23:56].