broadcast-rooms
Платформа трансляций: комнаты, расписание, архив с транскрипцией, таймкодами, буклетами
Source: ДобинДом
Files: 16
Stack:
DjangoDRFChannelsReactTanStack Query
Specification
broadcast-rooms
Назначение
Платформа для управления видео/аудио трансляциями: комнаты (разделы контента), расписание эфиров, архив записей с транскрипцией, таймкодами и генерацией PDF-буклетов. Три слоя: backend API, пользовательский фронтенд, админ-панель.
Контракты
Модели данных
class Room:
name: CharField(100, unique=True) # "Гостинная", "Кухня", "Своя комната"
description: TextField
image: ImageField # Обложка комнаты
sort_order: IntegerField
has_broadcast_text: BooleanField # Поддержка текстовых трансляций
is_library: BooleanField # Ведёт на библиотеку вместо архива
class Cycle:
name: CharField(200, unique=True) # Тематический цикл видео
sort_order: IntegerField
class BroadcastSchedule:
name: CharField(255) # Название трансляции
description: TextField
tags: CharField(500) # Через запятую
broadcast_datetime: DateTimeField
broadcast_type: CharField # 'video' | 'audio'
access_type: CharField # 'public' | 'private'
room: ForeignKey(Room)
audio_cover: ImageField # Обложка + auto-thumbnail 640px WebP
audio_cover_thumb: ImageField # Auto-generated
tariffs: ManyToManyField(Tariff) # Доступ по тарифам
class BroadcastText:
broadcast_schedule: OneToOneField(BroadcastSchedule)
content: TextField # Текст для синхронизации с видео
class TextBroadcastEvent:
broadcast_schedule: ForeignKey(BroadcastSchedule)
event_type: CharField # 'scroll' | 'highlight' | 'mark_block'
event_data: JSONField # {scroll_top}, {start, end}, {block_id}
time_seconds: FloatField # Время от начала эфира
class ArchivedBroadcast:
kinescope_video_id: CharField(unique=True) # UUID видео из видеохостинга
title: CharField(255)
broadcast_datetime: DateTimeField
broadcast_type: CharField # 'video' | 'audio'
room: ForeignKey(Room)
cycle: ForeignKey(Cycle)
access_type: CharField # 'public' | 'private'
is_visible: BooleanField
audio_cover: URLField # Обложка (URL)
cover_image: ImageField # Загруженная обложка (приоритет)
poster_url: URLField # Превью из видеохостинга
description: TextField
sort_order: IntegerField
# Транскрипция
transcription_status: CharField # 'none' | 'pending' | 'processing' | 'done' | 'error'
transcription_error: TextField
transcription_progress: CharField
# Таймкоды
timestamps_generation_status: CharField # 'pending' | 'processing' | 'done' | 'error'
timestamps_generation_error: TextField
# Буклет (PDF)
booklet_status: CharField
booklet_file: FileField
class VideoTimestamp:
broadcast: ForeignKey(ArchivedBroadcast)
time_seconds: PositiveIntegerField # Позиция в секундах
title: CharField(200) # Название момента
class VideoTranscription:
broadcast: OneToOneField(ArchivedBroadcast)
source: CharField # 'kinescope' | 'whisper'
content: TextField # Полный текст с временными меткамиAPI — расписание и комнаты (админ)
| Метод | Путь | Описание |
|---|
|-------|------|----------|
| GET/POST | /admin/rooms/ | Список/создание комнат |
|---|---|---|
| POST | /admin/rooms/{id}/remove-image/ | Удаление изображения |
| GET/POST | /admin/broadcasts/ | Список/создание расписания |
| GET/PUT/DELETE | /admin/broadcasts/{id}/ | CRUD трансляции |
| POST | /admin/broadcasts/{id}/remove-cover/ | Удаление обложки |
| POST | /admin/broadcasts/{id}/generate-cover/ | Генерация обложки (AI) |
| POST | /admin/broadcasts/{id}/set-cover/ | Установка сгенерированной обложки |
| POST | /admin/cabinet-text/ | Сохранение текста трансляции |
| POST | /admin/cabinet-text/{id}/event/ | Событие синхронизации текста (WebSocket) |
API — архив (админ)
| Метод | Путь | Описание |
|---|
|-------|------|----------|
| GET/POST | /admin/archive/ | Список/создание архивных записей (фильтры: room, is_visible, search, transcription_status) |
|---|---|---|
| POST | /admin/archive/{id}/transcribe/ | Запуск транскрипции |
| POST | /admin/archive/transcribe-all/ | Массовая транскрипция |
| GET/PATCH | /admin/archive/{id}/transcription/ | Текст транскрипции |
| GET/POST | /admin/archive/{id}/generate-timestamps/ | Генерация таймкодов (LLM) |
| GET/POST | /admin/archive/{id}/timestamps/ | CRUD таймкодов |
| GET/PUT/DELETE | /admin/archive/{id}/timestamps/{ts_id}/ | Детали таймкода |
| GET/POST | /admin/archive/{id}/generate-booklet/ | Генерация PDF-буклета |
API — пользовательский фронтенд
| Метод | Путь | Описание |
|---|
|-------|------|----------|
| GET | /rooms/ | Список комнат |
|---|---|---|
| GET | /archive/{id}/ | Детали видео с таймкодами |
| GET | /broadcasts/ | Текущее расписание |
| GET | /broadcasts/live/ | Активная трансляция |
Frontend hooks
// Пользовательский фронтенд
useRooms(): Room[]
useArchive(roomId?, accessType?): ArchivedBroadcast[]
usePublicBroadcast(): LiveBroadcast | null
// Админ-панель
useRooms(): Room[]
useCreateRoom(): mutation
useUpdateRoom(): mutation
useBroadcasts(): BroadcastSchedule[]
useCreateBroadcast(): mutation
useArchive(filters): ArchivedBroadcast[]
useTranscribe(id): mutation
useGenerateTimestamps(id): mutation
useGenerateBooklet(id): mutationРабочие процессы
**Создание трансляции:**
Admin → выбор комнаты → название, дата/время, тип (video/audio)
→ загрузка/генерация обложки → привязка тарифов доступа
→ (опционально) загрузка текстового контента
→ интеграция с видеохостингом → запуск live-события**Архивирование:**
Трансляция завершена → webhook → создание ArchivedBroadcast
→ транскрипция (Whisper / API видеохостинга)
→ генерация таймкодов (LLM) → генерация PDF-буклета
→ видео доступно в архиве пользователям**Текстовые трансляции:**
Admin загружает текст → начало эфира
→ спикер прокручивает / выделяет блоки
→ события по WebSocket → клиенты синхронизируют отображение
→ события сохраняются в БД для воспроизведения архиваЗависимости
•Django + DRF
•Celery/Huey (фоновые задачи: транскрипция, таймкоды, буклеты)
•django-solo (singleton settings)
•Django Channels (WebSocket для текстовых трансляций)
•Pillow (обложки, thumbnail)
•API видеохостинга (Kinescope, Vimeo, YouTube Live, или свой)
•LLM API (для генерации таймкодов и описаний)
•Whisper API (для транскрипции)
•React + TanStack Query (фронтенд)
Реализации
| Стек | Путь | Источник | Статус |
|---|
|------|------|----------|--------|
| Django + React (TypeScript) | implementations/django-react/ | ДобинДом | проверен |
|---|
Адаптация
•**Видеохостинг** — заменить Kinescope API на свой (Vimeo, YouTube, самохостинг). Точка интеграции: `services/api_client.py`.
•**Модель Tariff** — заменить связь `tariffs` M2M на свою систему подписок/доступа.
•**Комнаты** — переименовать «комнаты» в «каналы», «категории» или другую иерархию.
•**Текстовые трансляции** — опционально: убрать `BroadcastText` + `TextBroadcastEvent` если не нужна синхронизация текста.
•**Обложки** — заменить AI-генерацию (Gemini) на свой сервис или убрать.
•**Буклеты** — опционально: убрать генерацию PDF если не нужна.
•**LLM для таймкодов** — заменить промпт и модель в `services/timestamp_generator.py`.
•**Permissions** — заменить `IsStaffUser` на свою систему прав.