292 lines
12 KiB
Markdown
292 lines
12 KiB
Markdown
|
|
# Техническое задание: Совместное прослушивание музыки
|
|||
|
|
|
|||
|
|
## 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. Принятые решения
|
|||
|
|
|
|||
|
|
- **Аутентификация** — обязательная регистрация
|
|||
|
|
- **Права управления** — все участники могут управлять плеером
|
|||
|
|
- **Чат** — текстовый чат в каждой комнате
|
|||
|
|
- **Библиотека музыки** — общая для всех пользователей
|
|||
|
|
- **Приватность** — все комнаты публичные
|