Files
enigFM/TECHNICAL_SPEC.md
2025-12-12 13:30:09 +03:00

292 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Техническое задание: Совместное прослушивание музыки
## 1. Описание продукта
Веб-приложение для синхронного прослушивания музыки с друзьями в реальном времени. Пользователи создают комнаты, приглашают друзей по ссылке и слушают музыку одновременно.
## 2. Основные функции
### 2.1 Комнаты
- Создание комнаты (генерация уникального ID/ссылки)
- Публичные комнаты с возможностью поиска/списка
- Присоединение по ссылке или из списка комнат
- Отображение списка участников
### 2.2 Музыкальный плеер
- Воспроизведение MP3 из S3-хранилища
- Синхронизация playback между всеми участниками
- Управление доступно всем участникам: play/pause, перемотка, следующий/предыдущий трек
- Громкость (локальная, у каждого своя)
- Очередь воспроизведения (playlist)
- Отображение текущего трека, прогресса
### 2.3 Чат
- Текстовый чат внутри комнаты
- Сообщения видны всем участникам в реальном времени
### 2.4 Управление треками
- Загрузка MP3 файлов в S3
- Общая библиотека треков (доступна всем пользователям во всех комнатах)
- Добавление треков в очередь
- Базовые метаданные: название, исполнитель
### 2.5 Пользователи
- Обязательная регистрация/авторизация
- Профиль пользователя
## 3. Технические требования
### 3.1 Стек технологий
**Frontend:**
- Vue 3 (Composition API)
- Pinia (state management)
- Vue Router
- WebSocket клиент для real-time
**Backend:**
- Python
- FastAPI (REST API + WebSocket)
- SQLAlchemy (ORM)
- Alembic (миграции)
**База данных:**
- PostgreSQL
**Хранилище файлов:**
- S3 (FirstVDS)
### 3.2 Синхронизация
- WebSocket для real-time коммуникации
- Компенсация сетевой задержки
- Периодическая синхронизация позиции трека
### 3.3 Хранилище
- S3 (FirstVDS) для MP3 файлов
- Presigned URLs для безопасного доступа к файлам
- Ограничение размера файла: 10MB
- Лимит общего объёма хранилища: 90GB (проверка перед загрузкой)
### 3.4 Масштабируемость
- Лимит участников на комнату (например, 50)
- Автоудаление неактивных комнат
## 4. Схема базы данных
### users
| Поле | Тип | Описание |
|------|-----|----------|
| id | UUID | Первичный ключ |
| username | VARCHAR(50) | Уникальное имя пользователя |
| email | VARCHAR(255) | Email (уникальный) |
| password_hash | VARCHAR(255) | Хэш пароля |
| created_at | TIMESTAMP | Дата регистрации |
### rooms
| Поле | Тип | Описание |
|------|-----|----------|
| id | UUID | Первичный ключ |
| name | VARCHAR(100) | Название комнаты |
| owner_id | UUID (FK) | Создатель комнаты |
| current_track_id | UUID (FK) | Текущий трек |
| playback_position | INTEGER | Позиция воспроизведения (мс) |
| is_playing | BOOLEAN | Играет ли сейчас |
| created_at | TIMESTAMP | Дата создания |
### tracks
| Поле | Тип | Описание |
|------|-----|----------|
| id | UUID | Первичный ключ |
| title | VARCHAR(255) | Название трека |
| artist | VARCHAR(255) | Исполнитель |
| duration | INTEGER | Длительность (мс) |
| s3_key | VARCHAR(500) | Путь к файлу в S3 |
| uploaded_by | UUID (FK) | Кто загрузил |
| created_at | TIMESTAMP | Дата загрузки |
### room_queue
| Поле | Тип | Описание |
|------|-----|----------|
| id | UUID | Первичный ключ |
| room_id | UUID (FK) | Комната |
| track_id | UUID (FK) | Трек |
| position | INTEGER | Позиция в очереди |
| added_by | UUID (FK) | Кто добавил |
### room_participants
| Поле | Тип | Описание |
|------|-----|----------|
| room_id | UUID (FK) | Комната |
| user_id | UUID (FK) | Пользователь |
| joined_at | TIMESTAMP | Время входа |
### messages
| Поле | Тип | Описание |
|------|-----|----------|
| id | UUID | Первичный ключ |
| room_id | UUID (FK) | Комната |
| user_id | UUID (FK) | Автор |
| text | TEXT | Текст сообщения |
| created_at | TIMESTAMP | Время отправки |
## 5. API Endpoints
### Аутентификация
- `POST /api/auth/register` — регистрация
- `POST /api/auth/login` — вход
- `POST /api/auth/logout` — выход
- `GET /api/auth/me` — текущий пользователь
### Комнаты
- `GET /api/rooms` — список публичных комнат
- `POST /api/rooms` — создать комнату
- `GET /api/rooms/{id}` — информация о комнате
- `DELETE /api/rooms/{id}` — удалить комнату (только владелец)
- `POST /api/rooms/{id}/join` — присоединиться
- `POST /api/rooms/{id}/leave` — покинуть
### Плеер (через REST + WebSocket)
- `POST /api/rooms/{id}/play` — воспроизвести
- `POST /api/rooms/{id}/pause` — пауза
- `POST /api/rooms/{id}/seek` — перемотка
- `POST /api/rooms/{id}/next` — следующий трек
- `POST /api/rooms/{id}/prev` — предыдущий трек
### Очередь
- `GET /api/rooms/{id}/queue` — очередь треков
- `POST /api/rooms/{id}/queue` — добавить трек в очередь
- `DELETE /api/rooms/{id}/queue/{track_id}` — убрать из очереди
### Треки
- `GET /api/tracks` — библиотека треков
- `POST /api/tracks/upload` — загрузить трек
- `DELETE /api/tracks/{id}` — удалить трек
### Чат
- `GET /api/rooms/{id}/messages` — история сообщений
### WebSocket
- `WS /ws/rooms/{id}` — real-time события комнаты (синхронизация плеера, чат, участники)
## 6. Структура проекта
```
enigfm/
├── backend/
│ ├── app/
│ │ ├── __init__.py
│ │ ├── main.py # Точка входа FastAPI
│ │ ├── config.py # Конфигурация (env переменные)
│ │ ├── database.py # Подключение к БД
│ │ │
│ │ ├── models/ # SQLAlchemy модели
│ │ │ ├── __init__.py
│ │ │ ├── user.py
│ │ │ ├── room.py
│ │ │ ├── track.py
│ │ │ └── message.py
│ │ │
│ │ ├── schemas/ # Pydantic схемы
│ │ │ ├── __init__.py
│ │ │ ├── user.py
│ │ │ ├── room.py
│ │ │ ├── track.py
│ │ │ └── message.py
│ │ │
│ │ ├── routers/ # API роуты
│ │ │ ├── __init__.py
│ │ │ ├── auth.py
│ │ │ ├── rooms.py
│ │ │ ├── tracks.py
│ │ │ └── websocket.py
│ │ │
│ │ ├── services/ # Бизнес-логика
│ │ │ ├── __init__.py
│ │ │ ├── auth.py
│ │ │ ├── room.py
│ │ │ ├── track.py
│ │ │ ├── s3.py # Работа с S3
│ │ │ └── sync.py # Синхронизация плеера
│ │ │
│ │ └── utils/ # Утилиты
│ │ ├── __init__.py
│ │ └── security.py # JWT, хэширование
│ │
│ ├── alembic/ # Миграции БД
│ │ ├── versions/
│ │ └── env.py
│ │
│ ├── tests/
│ ├── requirements.txt
│ ├── alembic.ini
│ └── .env.example
├── frontend/
│ ├── src/
│ │ ├── main.js # Точка входа
│ │ ├── App.vue
│ │ │
│ │ ├── components/ # Vue компоненты
│ │ │ ├── player/
│ │ │ │ ├── AudioPlayer.vue
│ │ │ │ ├── PlayerControls.vue
│ │ │ │ ├── ProgressBar.vue
│ │ │ │ └── VolumeControl.vue
│ │ │ ├── room/
│ │ │ │ ├── RoomCard.vue
│ │ │ │ ├── RoomList.vue
│ │ │ │ ├── ParticipantsList.vue
│ │ │ │ └── Queue.vue
│ │ │ ├── chat/
│ │ │ │ ├── ChatWindow.vue
│ │ │ │ └── ChatMessage.vue
│ │ │ ├── tracks/
│ │ │ │ ├── TrackList.vue
│ │ │ │ ├── TrackItem.vue
│ │ │ │ └── UploadTrack.vue
│ │ │ └── common/
│ │ │ ├── Header.vue
│ │ │ └── Modal.vue
│ │ │
│ │ ├── views/ # Страницы
│ │ │ ├── HomeView.vue # Список комнат
│ │ │ ├── RoomView.vue # Страница комнаты
│ │ │ ├── LoginView.vue
│ │ │ ├── RegisterView.vue
│ │ │ └── TracksView.vue # Библиотека треков
│ │ │
│ │ ├── stores/ # Pinia stores
│ │ │ ├── auth.js
│ │ │ ├── room.js
│ │ │ ├── player.js
│ │ │ └── tracks.js
│ │ │
│ │ ├── composables/ # Vue composables
│ │ │ ├── useWebSocket.js
│ │ │ ├── usePlayer.js
│ │ │ └── useApi.js
│ │ │
│ │ ├── router/
│ │ │ └── index.js
│ │ │
│ │ └── assets/
│ │ └── styles/
│ │
│ ├── public/
│ ├── package.json
│ ├── vite.config.js
│ └── .env.example
├── docker-compose.yml # PostgreSQL, Backend, Frontend
├── .gitignore
└── README.md
```
## 7. Принятые решения
- **Аутентификация** — обязательная регистрация
- **Права управления** — все участники могут управлять плеером
- **Чат** — текстовый чат в каждой комнате
- **Библиотека музыки** — общая для всех пользователей
- **Приватность** — все комнаты публичные