Как создать видеосервер с поддержкой HLS для потокового вещания в реальном времени?

Здравствуйте! <br/><br/> У меня есть вопрос относительно реализации HLS отдачи на лету с использованием формата mp4. Интересно, как организовать процесс, при котором на сервере хранится только mp4 файл, а плейлист m3u8 и сегменты ts создаются динамически. <br/><br/> Примерные ссылки для реализации: <br/> - Отдача mp4: myvideocdn.stream/test/1080.mp4 <br/> - Отдача HLS плейлиста: myvideocdn.stream/test/1080.mp4:hls:manifest.m3u8 <br/> - Отдача сегмента: myvideocdn.stream/test/1080.mp4:hls:seg-571-v1-a1.ts <br/><br/> Также хотелось бы обсудить механизм подписки ссылок по IP адресу и времени жизни. Например, ссылка должна выглядеть так: myvideocdn.stream/test/98af0a6d1f2a2e067ba2f31ee1c4527f:2024111317/1080.mp4, чтобы быть доступной только для конкретного пользователя с соответствующим IP и действующим сроком действия. В то время как прямая не подписанная ссылка myvideocdn.stream/test/1080.mp4 должна быть недоступна. <br/><br/> Я знаю, что аналогичную схему использует ZeroCDN. Есть ли готовые решения, которые можно установить и настроить на собственных серверах для достижения такой функциональности?
  • 13 ноября 2024 г. 17:03
Ответы на вопрос 2
Создание видеосервера с поддержкой HLS (HTTP Live Streaming) для потокового вещания в реальном времени, включая динамическую генерацию плейлистов и сегментов, требует использования специальных инструментов и библиотек. Вот пошаговое руководство по реализации данной схемы:

### Шаг 1: Инструменты и сервер

1. **Выбор сервера**: Сначала вам нужно выбрать веб-сервер, который будет обрабатывать ваши запросы. Это может быть любой сервер (например, Nginx или Apache), однако Nginx часто используется вместе с модулем `nginx-rtmp-module` для стриминга видео.

2. **Кодеки и инкапсуляция**: Убедитесь, что ваши MP4-файлы использовали кодеки, которые поддерживаются HLS, такие как H.264 для видео и AAC для аудио.

### Шаг 2: Установка и настройка Nginx

1. **Установите Nginx**. Для этого можно воспользоваться следующими командами (для Ubuntu):
   ```bash
   sudo apt update
   sudo apt install nginx libnginx-mod-http-streaming
   ```

2. **Настройка Nginx**. Вы можете использовать следующий пример конфигурации в вашем файле `nginx.conf`:
   ```nginx
   http {
       ...
       server {
           listen 80;
           server_name myvideocdn.stream;

           location /test/ {
               # Локация для отдачи видеофайлов
               add_header Cache-Control no-cache;

               # Перенаправление на HLS
               if ($request_uri ~* "\.mp4:hls:manifest\.m3u8$") {
                   # Генерация плейлиста
                   # ваш код для генерации M3U8
               }
               
               if ($request_uri ~* "\.mp4:hls:seg-([0-9]+)-v[0-9]+-a[0-9]+\.ts$") {
                   # Генерация сегмента
                   # ваш код для генерации TS
               }
           }
       }
   }
   ```

### Шаг 3: Генерация HLS плейлистов и сегментов

Для динамической генерации M3U8 и TS файлов можно использовать языки программирования, такие как Python или PHP. Пример на Python:

```python
from flask import Flask, send_file, request
import os

app = Flask(__name__)

@app.route('/test/<file_id>:hls:manifest.m3u8')
def hls_manifest(file_id):
    # Формирование ссылки на MP4 файл
    mp4_file = f'/path/to/{file_id}.mp4'
    # Создание M3U8 файла на лету
    playlist = "#EXTM3U\n#EXT-X-VERSION:3\n#EXT-X-TARGETDURATION:10\n"
    for i in range(0, 5):  # Пример для 5 сегментов
        segment = f"{file_id}:hls:seg-{i}-v1-a1.ts"
        playlist += f"#EXTINF:10,\n{segment}\n"
    playlist += "#EXT-X-ENDLIST"
    return playlist, 200, {'Content-Type': 'application/vnd.apple.mpegurl'}

@app.route('/test/<file_id>:hls:seg-<segment_id>-v1-a1.ts')
def hls_segment(file_id, segment_id):
    # Генерация сегмента .ts
    ts_file = f'/path/to/{file_id}_{segment_id}.ts'
    return send_file(ts_file)

if __name__ == "__main__":
    app.run()
```

### Шаг 4: Подписка ссылок

Для реализации механизма подписки можно использовать JWT (JSON Web Tokens) или же создать специальный механизм подписки с параметрами IP и времени жизни.

Пример создания подписанной ссылки:
```python
import jwt
import time

def generate_signed_url(file_id, user_ip):
    payload = {
        'file_id': file_id,
        'ip': user_ip,
        'exp': time.time() + 3600,  # Срок действия 1 час
    }
    signed_url = jwt.encode(payload, 'secret', algorithm='HS256')
    return f'myvideocdn.stream/test/{signed_url}/{file_id}.mp4'

# Проверка подписанной ссылки
def check_signed_url(encoded_jwt):
    try:
        payload = jwt.decode(encoded_jwt, 'secret', algorithms=['HS256'])
        # Здесь добавить проверку IP
        return payload['file_id']
    except jwt.ExpiredSignatureError:
        return None
```

###
выбор не то чтобы сильно велик 

ffmpeg https://www.mux.com/articles/how-to-convert-mp4-to...
nginx-rtmp-module возможно пригодится https://github.com/TareqAlqutami/rtmp-hls-server
Похожие вопросы