PHP CookBook: MyPHPTube.com (клонируем YouTube)
// Estimation

С возросшей популярностью сервиса YouTube.com многим захотелось организовать подобный сервис, но как это сделать? Приведу небольшой рецепт организации такого сервиса.
Функциональность
Для начала опишем основной функционал сайта (сразу определимся и с ролями пользователей):
- Гость
- просмотр видеофайлов на сайте
- Пользователь
- аплоад видеофайлов
- Администратор
- управление пользователями
- управление файлами
WEB 2.0 фичи
А теперь расширем наш базовый функционал, чтобы привлечь аудиторию:
- Гость
- просмотр комментариев к видеофайлам
- поиск файлов (по категории, по тегам)
- Пользователь
- возможность оставлять комментарии к видеофайлам
- возможность записывать видеофайлы с web-камеры
- возможность связывать видеоролик с категорией
- возможность связывать видеоролик с несоклькими тегами (tags)
- выставление рейтинга видеофайла
- организация списка друзей
- внутренняя mail система
- закладки
- Администратор
- управление комментариями
- управление категориями
Это конечно не весь функционал YouTube, но ведь нужно с чего-то начинать
Конфигурация сервера
Наша система будет базироваться на LAMP:
- Linux
- Apache (версия 2.2 и выше)
- MySQL (версия 5.0 и выше)
- PHP (версия 5.2 и выше)
Возможные проблемы
А теперь расскажем о проблемах с которыми Вам предстоит столкнуться
Конвертирование Видео
Если позволить каждому из посетителей сайта заливать на сервер видеоролики в произвольном формате, то для того, чтобы просмотреть их все, Вам прийдется устанавливать на свой компьютер очень много кодеков, а если требовать определенный формат от пользователя – то, с очень большой вероятностью, это отпугнет от вашего сайта поситителей. И что же делать? Правильно, конвертировать все видеофайлы в один формат, и будем конфертировать в формат FLV (flash video – можно просматривать в большинстве операционных систем, поскольку он использует широко распространённый Adobe Flash Player и плагины к большинству браузеров, а также поддерживается многими программами для воспроизведения видео, например, MPlayer, VLC media player и другими программами, работающими с помощью DirectShow).
Нам понадобятся следующие програмные средства (всё opensource):
- mencoder или FFmpeg
- flvtool2 (требует наличия Ruby)
- PHP Program Package (‘example.php’ пример конвертации с использованием mencoder’a) или ffmpeg class (‘ffmpeg.example1.php’ пример конвертации с использованием ffmpeg)
Дополнительно можно еще использовать mplayer для получения информации о оригинальном видеоролике.
Замечательно, если мы всё установили и правильно собрали, то мы теперь можем конвертировать…
Статус загрузки
Еще такой момент – пользователям не нравиться сидеть и ждать пока файл загрузится на сервер, пользователь он же любознательный, ему хотя бы вывести progress bar надо:
- http://www.emllabs.com/article.php?articleId=121/ (используя Flash8 и PHP)
- http://tomas.epineer.se/tesupload/
- http://www.raditha.com/megaupload/
- http://www.obokaman.com/p/descripcion-y-fuentes-del-upload-php-ajax-con-barra-de-progreso-1596
- http://labs.beffa.org/w2box/demo/
- http://trydobe.com/?page_id=3
- http://ecosmear.com/relay/ (прикольный примерчик, используется perl)
Все ссылки нарыл на форуме xajax’a http://community.xajaxproject.org/viewtopic.php?pid=10100
Ресурсы
Так, на сервер мы залили видеофайл, показали как он быстро к нам заливался, но вот беда, если мы будем на нашем web-сервере конвертировать видео ролики – то сайт у нас будет скорее мёртв, чем жив. Для этой цели нам надо будет использовать еще один (как минимум) сервер, который будет забирать неотконвертированный файлы с web-сервера и отправлять назад отконвертированные ролики. Т.е. для решение данной проблемы нам понадобиться еще железо…
Распределение нагрузки
Конвертирование это ресурсоемко, а отдавать видеоролики всем желающим?… Это конечно не будет так нагружать процессор, но вот канал точно умрет… как выход у нас появляются еще сервера, которые и хранят у себя видеофайлы:
Как распределять нагрузку – это уже решать Вам. Но прежде, чем городить огород Вы должны определить какой приблизительно объем данных Вам прийдеться хранить, и далее уже решать какая схема больше подойдет, ориентируемся, что 1 пользователь заливает на сервер 20mb в месяц (234Gb на 1000 пользователей в год), не популярные ролики не сохраняются более года):
- Объём данных ~ 0.3Tb – 1.5Tb:
на каждом зеркале у нас хранятся все видеоролики
у нас есть mirror1 – сервер на котором всегда первым появляется переконвертированный видеоролик, остальные с ним синхронизируются - Объём данных ~ 1.5Tb – 3 Tb:
все видеоролики храняться только на одном главном сервере, если у видеоролика растет популярность, он заливается и на другие зеркала - Объём данных > 3Tb:
видеролик заливается на ближайшее зеркало (подразумеваем, что ролик залитый китайцем будут смотреть в основном китайцы, следовательно заливаем его на зеркало в Китае)
по мере роста популярности ролика зеркалим его на сервер ближайший к эпицетру популярности (пример: китаец живет в США, его ролик залит на зеркало расположенное в США, смотрят его в основном в Китае, видя это ролик будет отзеркален на Китайский сервер)
Числа взяты с потолка, против китайцев ничего не имею (просто взяты для примера), пишите свои варианты…
База данных
Далее я опишу простенькую архитектуру БД:
| users | |
|---|---|
| id | autoincrement field |
| login | unique login |
| password | encrypt password |
| user email | |
| actcode | activation code |
| role | ENUM(guest/user/admin) |
| status | not active / active / disable |
| date_create | |
| date_update | date of last change profile |
| date_login | date of last login |
| … | another fields e.g. first name, last name |
| friends | |
|---|---|
| id | autoincrement field |
| user_id1 | user ID |
| user_id2 | user ID |
| status | request / ok / cancel |
| date_create | date of send request |
| date_update | date of accept or denied request |
| files | |
|---|---|
| id | autoincrement field |
| title | title of video file |
| file | name of file on file system |
| status | not convert / in process / ok |
| access | public / members only / friends only / private |
| author_id | ID of owner (users) |
| category_id | ID of category (categories) |
| date_create | |
| date_update | date of last changes |
| … | another fields e.g. length, description |
| mirrors | |
|---|---|
| id | autoincrement field |
| url | mirror url |
| date_create | |
| date_update | date of last changes |
| mirrors_link | |
|---|---|
| file_id | ID of file (files) |
| mirror_id | ID of mirror (mirrors) |
| status | current file status downloading / ok |
| date_create | |
| date_update | date of last changes |
| categories | |
|---|---|
| id | autoincrement field |
| pid | parent category ID |
| name | name of category |
| … | another fields e.g. metadescription, metakeywords |
| tags | |
|---|---|
| id | autoincrement field |
| word | tag word |
| tags_link | |
|---|---|
| id | autoincrement field |
| tag_id | tag ID (tags) |
| file_id | file ID (files) |
| comments | |
|---|---|
| id | autoincrement field |
| author_id | ID of owner (users) |
| file_id | file ID (files) |
| message | text of message |
| date_create | |
| rate | |
|---|---|
| id | autoincrement field |
| author_id | ID of owner (users) |
| file_id | file ID (files) |
| rate | integer value, e.g. for 0 to 10 |
| date_create | |
| messages | |
|---|---|
| id | autoincrement field |
| author_id | ID of owner (users) |
| user_id | ID of recipient (users) |
| type | e.g. friend request-response / admin message |
| author_folder | outbox/draft/delete |
| user_folder | inbox/delete |
| user_status | read or not |
| date_create | |
| bookmarks | |
|---|---|
| id | autoincrement field |
| author_id | ID of owner (users) |
| file_id | file ID (files) |
| title | title of link |
| description | some description |
| date_create | |
Небольшое примечание:
- для полей ввида date_create и date_update используем функцию gmdate(’Y-m-d H:i:s’) – время по Гринвичу, это облегчит в дальнейшем жизнь при отображении времени на сайте.
Команда
Какую лучше всего собрать команду для разработки такого проекта? Я предлагаю следующий вариант:
- 2 PHP-разработчика
- Flash разработчик / дизайнер
- 1 администратор
- 1 тестировщик
- 1 менеджер
Оценка
| Гость | ||
|---|---|---|
| Статические странички | такие как “Contact Us”, “Terms of Use” etc. | 1h/page |
| Поиск | простенький поиск по нескольким параметрам | 6h |
| Облако тэгов | 8h | |
| Просмотр видео | FLV video player | 16h |
| Просмотр комментариев | 6h | |
| Регистрация | включая валидацию e-mail | 12h |
| Напоминалка пароля | 2h | |
| Пользователь | ||
| Login/Logout | 2h | |
| Upload file | 14h | |
| Запись видео | Необходим один из следующих серверов: FMS, Wowza (from Feb 2007) or Red5 (opensource) |
16h |
| Progress bar | 16h | |
| Добавление комментария | 4h | |
| Система рейтингов | 2h | |
| Закладки | create/edit/delete | 8h |
| Администратор | ||
| Управление пользователями | Список пользователей, просмотр и редактирование профайлов | 16h |
| Управление категориями | 16h | |
| Остальное | ||
| Дизайн | 32h | |
| Разработка БД | 16h | |
| Разработка архитектуры | 32h | |
| Хранилище файлов | от 8h до 96h | 8h |
| Конвертирование видеофайлов | 20h | |
| Итого | ||
| Настройка серверов | web-server, convert-server, mirrors | 40h |
| Разработка | 256h | |
| Тестирование | 30%-50% от разработки | 85h |
| Менеджмент | 10% минимум | 40h |
| Итого: 421h | ||
Да уж, не мало – 421 часа, т.е. примерно 2,5 месяца разработки… и это еще очень оптимистическая оценка, с учётом, что разработчики используют свои наработки или какую-либо CMF систему аналогичную Zend Framework или phpXCore, а так же организовываем простейшее хранилище файлов. Если же разработка будет вестись с нуля – то можно смело умножать данную оценку на 2.
Итого, такой проект будет стоить не менее $10 000…
P.S.
Основная проблема не в реализации системы, а в привличениии аудитории, кто будет пользоваться вашим сервисом если есть YouTube (и даже PornoTube)? Чем завлечь? Если есть идеи – пишите каменты…
На момент написания статьи домен MyPHPTube.com не был зарегистрирован, если вы его таки зарегистрировали, вышлете пива на мой домашний адрес… ;)
Есть несколько причин побудивших написать данную статью:
- хотелось написать умную статью для своего блога (или претендующую на “умную”)
- хотелось показать, что Package Program таки может пригодиться
- продемонстрировать, что OpenSource и LAMP тоже рулит ;)