html текст
All interests
  • All interests
  • Design
  • Food
  • Gadgets
  • Humor
  • News
  • Photo
  • Travel
  • Video
Click to see the next recommended page
Like it
Don't like
Add to Favorites

Создание полноценного видеохостинга своими руками (nginx+php5-fpm+ffmpeg+cumulusclips) из песочницы

Добрый день, хабровчане!

Недавно в нашей компании возникла потребность создания своего видеоресурса, закрытого, но в тоже время немного публичного. И вот наконец, он закончен и я готов поделиться знаниями и применениями.

Задача была следующая:
Создать видеоресурс, способный проводить многопоточные односторонние трансляции с web камеры, а так же из любого файла (это например для защиты от прямого скачивания), видеошару с возможностью просмотреть видео в разных форматах и битрейтах.

В основу лег освободившийся сервер! Не очень мощный, но довольно таки подходящий.

Intel® Xeon® CPU L5520 @ 2.27GHz
количество ядер 16
оперативной памяти 16372 Мб


Немного забегу вперед, при декодировании видео процессорная нагрузка достигает 500% (примерно 6 ядер);

Начнем с самого начала, из ОС я выбрал Ubuntu Server 13.04 x64 ввиду того, что больше времени провожу с ней и собственно разбираюсь я в ней лучше чем в других семействах Linux.

В качестве WEB сервера я выбрал связку nginx+php5-fpm, потому что nginx довольно успешно справляется с нагрузками, а так же отдачей видео.

nginx по умолчанию ставится без потокового модуля, поэтому ставим из сорцов

Необходимые зависимости для сборки пакетов:

apt-get install build-essential checkinstall subversion unzip yamdi imagemagick php5-curl libssl-dev zlib1g-dev libpcre3-dev rpl php5-fpm git


Скачиваем исходники:

cd /tmp
wget http://nginx.org/download/nginx-1.5.2.zip
unzip nginx-1.5.2.zip -d nginx/
rm -f nginx-1.5.2.zip
cd nginx


Скачиваем необходимые модули для стриминга:

mkdir modules
git clone https://github.com/masterzen/nginx-upload-progress-module.git modules/nginx-upload-progress-module
wget http://www.kernel-video-sharing.com/files/nginx_mod_h264_streaming-2.3.2.zip
unzip nginx_mod_h264_streaming-2.3.2.zip -d modules/
rm -f nginx_mod_h264_streaming-2.3.2.zip
git clone https://github.com/arut/nginx-rtmp-module.git modules/nginx-rtmp-module


Для удобства создаем установочный скрипт:

touch nginx.sh
nano nginx.sh

с содержимым
./configure \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--http-log-path=/var/log/nginx/access.log \
--http-client-body-temp-path=/var/lib/nginx/body \
--http-proxy-temp-path=/var/lib/nginx/proxy \
--http-fastcgi-temp-path=/var/lib/nginx/fastcgi \
--with-debug \
--with-http_stub_status_module \
--with-http_secure_link_module \
--with-http_gzip_static_module \
--with-http_realip_module \
--with-http_mp4_module \
--with-http_flv_module \
--with-http_ssl_module \
--with-http_dav_module \
--with-md5=/usr/lib \
--add-module=modules/nginx-upload-progress-module \
--add-module=modules/nginx-rtmp-module \
--add-module=modules/nginx_mod_h264_streaming-2.3.2  

make -j16 (16 - количество ядер. ускоряет сборку пакета. Можно узнать командой "grep -c processor /proc/cpuinfo")

checkinstall


Возможно в процессе компиляции могут возникнуть ошибки. Поэтому делаем так:

В файле auto/cc/gcc комментируем строчку:

#CFLAGS="$CFLAGS -Werror"


Запускаем:
sh nginx.sh


После установки создаем необходимые симлинки и директории (если не создались):

ln -s /usr/local/nginx/sbin/nginx /usr/sbin/nginx
mkdir -p /var/lib/nginx/body
mkdir /var/lib/nginx/proxy
mkdir /var/lib/nginx/fastcgi
chown -R root /var/lib/nginx/
wget http://nginx-init-ubuntu.googlecode.com/files/nginx-init-ubuntu_v2.0.0-RC2.tar.bz2
tar -jxvf nginx-init-ubuntu_v2.0.0-RC2.tar.bz2 -C /etc/init.d/
chmod 715 /etc/init.d/nginx
/usr/sbin/update-rc.d -f nginx defaults
rm -f nginx-init-ubuntu_v2.0.0-RC2.tar.bz2
rpl 'DAEMON=/usr/local/sbin/nginx' 'DAEMON=/usr/local/nginx/sbin/nginx' /etc/init.d/nginx
rpl 'NGINX_CONF_FILE="/usr/local/nginx/conf/nginx.conf"' 'NGINX_CONF_FILE="/etc/nginx/nginx.conf"' /etc/init.d/nginx


На этом установка nginx и php5-fpm завершена.
К настройке вернемся позже.

Следующим на очереди стоит ffmpeg. Установка apt-get не желательна, проект уже депрекейтет и многое отказывается работать. В поисках адекватной и более свежей инструкции я провел почти 2 ночи. Не скрою, нашел доповольно таки хороший пак для установки.

Как ни странно проект называется www.ffmpeginstaller.com и даже при наличии всех инсталяторов в открытом доступе предлагает свои услуги за 50 баксов.

А делается все довольно просто.
Скачиваем пакет:

cd  /tmp
wget http://mirror.ffmpeginstaller.com/old/scripts/ffmpeg7/ffmpeginstaller.7.4.tar.gz
tar -xzf ffmpeginstaller.7.4.tar.gz ffmpeg
cd ffmpeg


После первой установки я понял… не хватает кодека. Отмотаем <<< Ставим кодек до установки:

apt-get install libvpx


Открываем ffmpeg.sh и добавляем кодек "--enable-libxvid" в установку:

nano ffmpeg.sh
./configure --prefix=$INSTALL_DDIR --enable-shared --enable-nonfree \
                --enable-gpl --enable-pthreads  --enable-libopencore-amrnb  --enable-decoder=liba52 \
                --enable-libopencore-amrwb  --enable-libfaac  --enable-libmp3lame \
                --enable-libtheora --enable-libvorbis  --enable-libx264  --enable-libxvid --enable-libvpx \
                --extra-cflags=-I/usr/local/cpffmpeg/include/ --extra-ldflags=-L/usr/local/cpffmpeg/lib \
                --enable-version3 --extra-version=syslint


На этом подготовка завершена. Можно устанавливать: sh install.sh

Установка займет минут 15-20 в зависимостти от возможностей железа. Можно пойти попить чаю (или кофе).

После установки выполняем:

hash x264 ffmpeg ffplay


Все. Поздравляю, мы это сделали!

Теперь нам нужна CMS для управления этими инструментами

Вариантов было немного, а точнее всего 2 (а под мои нужды подходила только одна — cumulusclips).
Код исходников понятен, без лишней нервотрепки разобрался с составляющей. Вот только пришлось проект переписывать с mysql на mysqli. Весь код CMS структурирован и темлпейты лежат отдельно и гибко настраиваются. За основу выбрал шаблон псевдо Ютуба.

Пришлось полностью перекрутить проигрыватель, т.к. jwplayer был неспособен переключать видеопотоки. Немного полазив по github нашел незамысловатый плеер под простым названием jQplayer.
Данный плеер способен легко переключать потоки. Правда есть один минус. Проигрывание файла начинается с начала. И это не оказалось проблемой — видеофайлы легко режутся nginx из коробки.

Теперь нам нужно настроить web хостинг для нашего проекта.
Прилагаю небольшой скрипт для автоматизации данного процесса. В комплекте с CMS лежал .htaccess — а nginx его понимать отказывается, поэтому я его переписал под нужды данного web сервера.

#!/bin/bash
echo -n "Введите имя создаваемого хоста: " 
read host 
echo -n "Введите имя пользователя nginx: " 
read users 
sap=/etc/nginx/sites-available/$host.conf 
mkdir -p /var/hosting/
touch $sap 
chmod 777 $sap 
directives="upstream backend-${host} {server unix:/var/run/php5-${host}.sock;} 
server {
    listen 80;
    server_name ${host} www.${host};
    root /var/hosting/${host}/www;
    access_log /var/log/nginx/${host}-access.log;
    error_log /var/log/nginx/${host}-error.log;
    index index.php;
    rewrite_log on;
    if ($host = '${host}' ) {
        rewrite ^/(.*)$ http://www.${host}/$1 permanent;
    }    
    location /im {
        rewrite ^/im/(.*)$ /cc-core/controllers/thumbs.php?$1 last;
    }
    location /videos {
        rewrite ^/videos/([0-9]+)/(.*)$ /cc-core/controllers/play.php?vid=$1 last;
        rewrite ^/videos/page/([0-9]+)/$ /cc-core/controllers/videos.php?page=$1 last;
        rewrite ^/videos/(most-recent|most-viewed|most-discussed|most-rated)/$ /cc-core/controllers/videos.php?load=$1 last;
        rewrite ^/videos/(most-recent|most-viewed|most-discussed|most-rated)/page/([0-9]+)/$ /cc-core/controllers/videos.php?load=$1&page=$2 last;
        rewrite ^/videos/([a-zA-Z0-9\-]+)/$ /cc-core/controllers/videos.php?category=$1 last;
        rewrite ^/videos/([a-zA-Z-]+)/page/([0-9]+)/$ /cc-core/controllers/videos.php?category=$1&page=$2 last;
        rewrite ^/videos/([0-9]+)/comments/$ /cc-core/controllers/comments.php?vid=$1 last;
        rewrite ^/videos/([0-9]+)/comments/page/([0-9]+)/$ /cc-core/controllers/comments.php?vid=$1&page=$2 last;
        rewrite ^/videos/$ /cc-core/controllers/videos.php last;
    }    
    location /private {
        rewrite ^/private/get/$ /cc-core/controllers/play.php?get_private=true last;
        rewrite ^/private/videos/([a-zA-Z0-9]+)/$ /cc-core/controllers/play.php?private=$1 last;
        rewrite ^/private/comments/([a-zA-Z0-9]+)/$ /cc-core/controllers/comments.php?private=$1 last;
        rewrite ^/private/comments/([a-zA-Z0-9]+)/page/([a-z0-9]+)/$ /cc-core/controllers/comments.php?private=$1&page=$2 last;
    }    
    location /members {        
        rewrite ^/members/page/([0-9]+)/$ /cc-core/controllers/members.php?page=$1 last;
        rewrite ^/members/([a-zA-Z0-9]+)/$ /cc-core/controllers/profile.php?username=$1 last;
        rewrite ^/members/([a-zA-Z0-9]+)/videos/$ /cc-core/controllers/member_videos.php?username=$1 last;
        rewrite ^/members/([a-zA-Z0-9]+)/videos/page/([0-9]+)/$ /cc-core/controllers/member_videos.php?username=$1&page=$2 last;
        rewrite ^/members/$ /cc-core/controllers/members.php last;
    }    
    location /search {
        rewrite ^/search(/page/([0-9]+))?/$ /cc-core/controllers/search.php?page=$2 last;
    }    
    location /login {
        rewrite ^(.*)$ /cc-core/controllers/login.php last;
    }    
    location /login/forgot {
        rewrite ^(.*)$ /cc-core/controllers/login.php?action=forgot last;
    }    
    location /logout {
        rewrite ^(.*)$ /cc-core/system/logout.php last;
    }    
    location /register {
        rewrite ^(.*)$ /cc-core/controllers/register.php last;
    }    
    location /activate {
        rewrite ^(.*)$ /cc-core/controllers/activate.php last;
    }    
    location /opt {
        rewrite ^/opt-out/$ /cc-core/controllers/opt_out.php last;
    }    
    location /contact {
        rewrite ^(.*)$ /cc-core/controllers/contact.php last;
    }    
    location /embed {
        rewrite ^/embed/([0-9]+)/$ /cc-core/system/embed.php?vid=$1 last;
    }    
    location /page {
        rewrite ^(.*)$ /cc-core/system/page.php last;
    } 
    location /translation {
        rewrite ^(.*)$ /cc-core/system/translation.php last;
    }    
    location /notify {
        rewrite ^(.*)$ /cc-core/system/notify.php last;
    }    
    location /language/get {
        rewrite ^(.*)$ /cc-core/system/language.php?get last;
    }    
    location /language {
        rewrite ^/language/set/(.*)/$ /cc-core/system/language.php?set&language=$1 last;
    }    
    location /feed {
        rewrite ^/feed(/([a-zA-Z0-9]+))?/$ /cc-core/system/feed.php?username=$2 last;
    }    
    location /video {
        rewrite ^/video-sitemap(-([0-9]+))?\.xml$ /cc-core/system/video_sitemap.php?page=$2 last;
    }    
    location /myaccount/upload/avatar {
        rewrite ^(.*)$ /cc-core/system/avatar.ajax.php last;
    }    
    location /myaccount/upload/validate {
        rewrite ^(.*)$ /cc-core/system/upload.ajax.php last;
    }    
    location /myaccount/grab/validate {
        rewrite ^(.*)$ /cc-core/system/grab.ajax.php last;
    }    
    location /actions/username {
        rewrite ^(.*)$ /cc-core/system/username.ajax.php last;
    }    
    location /actions/flag {
        rewrite ^(.*)$ /cc-core/system/flag.ajax.php last;
    }    
    location /actions/favorite {
        rewrite ^(.*)$ /cc-core/system/favorite.ajax.php last;
    }    
    location /actions/subscribe {
        rewrite ^(.*)$ /cc-core/system/subscribe.ajax.php last;
    }    
    location /actions/rate {
        rewrite ^(.*)$ /cc-core/system/rate.ajax.php last;
    }    
    location /actions/comment {
        rewrite ^(.*)$ /cc-core/system/comment.ajax.php last;
    }    
    location /actions/post {
        rewrite ^(.*)$ /cc-core/system/post.ajax.php last;
    } 
    location /actions/stream {
        rewrite ^(.*)$ /cc-core/system/stream.ajax.php last;
    }    
    location /actions {
        rewrite ^/actions/mobile-(videos|search)/$ /cc-core/system/mobile_$1.ajax.php?mobile last;
    }   
    location /myaccount {        
        rewrite ^/myaccount/upload/complete/$ /cc-core/controllers/myaccount/upload_complete.php last;
        rewrite ^/myaccount/upload/video/$ /cc-core/controllers/myaccount/upload_video.php last;
        rewrite ^/myaccount/upload/$ /cc-core/controllers/myaccount/upload.php last;
        rewrite ^/myaccount/myvideos(/page/([0-9]+))?/$ /cc-core/controllers/myaccount/myvideos.php?page=$2 last;
        rewrite ^/myaccount/myvideos/([0-9]+)/$ /cc-core/controllers/myaccount/myvideos.php?vid=$1 last;
        rewrite ^/myaccount/editvideo/([0-9]+)/$ /cc-core/controllers/myaccount/edit_video.php?vid=$1 last;
        rewrite ^/myaccount/myfavorites(/page/([0-9]+))?/$ /cc-core/controllers/myaccount/myfavorites.php?page=$2 last;
        rewrite ^/myaccount/myfavorites/([0-9]+)/$ /cc-core/controllers/myaccount/myfavorites.php?vid=$1 last;
        rewrite ^/myaccount/privacy-settings/$ /cc-core/controllers/myaccount/privacy_settings.php last;
        rewrite ^/myaccount/change-password/$ /cc-core/controllers/myaccount/change_password.php last;
        rewrite ^/myaccount/subscriptions(/([0-9]+))?/$ /cc-core/controllers/myaccount/subscriptions.php?id=$2 last;
        rewrite ^/myaccount/subscriptions(/page/([0-9]+))?/$ /cc-core/controllers/myaccount/subscriptions.php?page=$2 last;
        rewrite ^/myaccount/subscribers(/page/([0-9]+))?/$ /cc-core/controllers/myaccount/subscribers.php?page=$2 last;
        rewrite ^/myaccount/message/inbox(/page/([0-9]+))?/$ /cc-core/controllers/myaccount/message_inbox.php?page=$2 last;
        rewrite ^/myaccount/message/inbox/([0-9]+)/$ /cc-core/controllers/myaccount/message_inbox.php?delete=$1 last;
        rewrite ^/myaccount/message/read/([0-9]+)/$ /cc-core/controllers/myaccount/message_read.php?msg=$1 last;
        rewrite ^/myaccount/message/send/([a-zA-Z0-9]+)/$ /cc-core/controllers/myaccount/message_send.php?username=$1 last;
        rewrite ^/myaccount/message/reply/([0-9]+)/$ /cc-core/controllers/myaccount/message_send.php?msg=$1 last;
        rewrite ^/myaccount/$ /cc-core/controllers/myaccount/myaccount.php last;
    }    
    location /myaccount/profile {
        rewrite ^(.*)$ /cc-core/controllers/myaccount/update_profile.php last;
    }    
    location /myaccount/profile/reset {
        rewrite ^(.*)$ /cc-core/controllers/myaccount/update_profile.php?action=reset last;
    }
    location /myaccount/message/send {
        rewrite ^(.*)$ /cc-core/controllers/myaccount/message_send.php last;
    }    
    location /m {
        rewrite ^/m/v/([0-9]+)/$ /cc-core/controllers/mobile/play.php?mobile&vid=$1 last;
        rewrite ^/m/v/$ /cc-core/controllers/mobile/videos.php?mobile last;
        rewrite ^/m/s/$ /cc-core/controllers/mobile/search.php?mobile last;
        rewrite ^/m/$ /cc-core/controllers/mobile/index.php?mobile last;
    }    
    location /system {
        rewrite ^/system-error/$ /cc-core/controllers/system_error.php last;
    }
    location /t {
        rewrite ^/t/(.*)$ /cc-core/system/translation.php last;
    }
    location / {
        if (!-e $request_filename){
            #rewrite ^/(.*)$ /$request_uri/ permanent;            
            rewrite ^/(.*)$ /cc-core/system/page.php last;
        }
    }
    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass backend-${host};
    }
    location ~* ^.+\.(jpg|jpeg|gif|css|png|js|ico|bmp)$ {
        access_log off;
        expires 10d;
        break;
    }
    location ~ \.(flv|mp4|webm|ogg|ogv|mp3)$ {
        mp4;
        mp4_buffer_size     1m;
        mp4_max_buffer_size 5m;        
    }
    location ~ /\. {
        deny all;
    }
}
" 
echo "$directives">$sap 
sap_poll=/etc/php5/fpm/pool.d/$host.conf 
touch $sap_poll 
chmod 777 $sap_poll 
directives_poll="[${host}]
	listen = /var/run/php5-${host}.sock
	listen.mode = 0666
	user = ${users}
	group = ${users}
	chdir = /var/hosting/${host}
	php_admin_value[upload_tmp_dir] = /var/hosting/${host}/tmp
	php_admin_value[soap.wsdl_cache_dir] = /var/hosting/${host}/tmp
	php_admin_value[date.timezone] = Asia/Yekaterinburg
	pm                                  = dynamic
    pm.min_spare_servers                = 10
    pm.max_spare_servers                = 20
    pm.start_servers                    = 10
    pm.max_children                     = 40" 
echo "$directives_poll">$sap_poll 
ln -s /etc/nginx/sites-available/$host.conf /etc/nginx/sites-enabled/$host.conf 
mkdir -p /var/hosting/$host/www/ 
mkdir -p /var/hosting/$host/tmp/ 
dir=/var/hosting/$host/www 
chown -R $users:$users "$dir"; 
find "$dir" -type d -exec chmod 0755 '{}' \; 
find "$dir" -type f -exec chmod 0644 '{}' \; 
/etc/init.d/nginx restart
/etc/init.d/php5-fpm restart



На этом все. Данная конфигурация способна кодировать видео в разные форматы, а так же стримить поток. Если данная статья заинтересует кого либо, я с удовольствием приведу живые примеры стриминга.

К сожалению полной начинки показать не могу, но вот что получилось у меня stream.etagi.com

Спасибо за внимание.
Читать дальше
Twitter
Одноклассники
Мой Мир

материал с habrahabr.ru

1

      Add

      You can create thematic collections and keep, for instance, all recipes in one place so you will never lose them.

      No images found
      Previous Next 0 / 0
      500
      • Advertisement
      • Animals
      • Architecture
      • Art
      • Auto
      • Aviation
      • Books
      • Cartoons
      • Celebrities
      • Children
      • Culture
      • Design
      • Economics
      • Education
      • Entertainment
      • Fashion
      • Fitness
      • Food
      • Gadgets
      • Games
      • Health
      • History
      • Hobby
      • Humor
      • Interior
      • Moto
      • Movies
      • Music
      • Nature
      • News
      • Photo
      • Pictures
      • Politics
      • Psychology
      • Science
      • Society
      • Sport
      • Technology
      • Travel
      • Video
      • Weapons
      • Web
      • Work
        Submit
        Valid formats are JPG, PNG, GIF.
        Not more than 5 Мb, please.
        30
        surfingbird.ru/site/
        RSS format guidelines
        500
        • Advertisement
        • Animals
        • Architecture
        • Art
        • Auto
        • Aviation
        • Books
        • Cartoons
        • Celebrities
        • Children
        • Culture
        • Design
        • Economics
        • Education
        • Entertainment
        • Fashion
        • Fitness
        • Food
        • Gadgets
        • Games
        • Health
        • History
        • Hobby
        • Humor
        • Interior
        • Moto
        • Movies
        • Music
        • Nature
        • News
        • Photo
        • Pictures
        • Politics
        • Psychology
        • Science
        • Society
        • Sport
        • Technology
        • Travel
        • Video
        • Weapons
        • Web
        • Work

          Submit

          Thank you! Wait for moderation.

          Тебе это не нравится?

          You can block the domain, tag, user or channel, and we'll stop recommend it to you. You can always unblock them in your settings.

          • habrahabr.ru
          • домен habrahabr.ru

          Get a link

          Спасибо, твоя жалоба принята.

          Log on to Surfingbird

          Recover
          Sign up

          or

          Welcome to Surfingbird.com!

          You'll find thousands of interesting pages, photos, and videos inside.
          Join!

          • Personal
            recommendations

          • Stash
            interesting and useful stuff

          • Anywhere,
            anytime

          Do we already know you? Login or restore the password.

          Close

          Add to collection

             

            Facebook

            Ваш профиль на рассмотрении, обновите страницу через несколько секунд

            Facebook

            К сожалению, вы не попадаете под условия акции