📜 ⬆️ ⬇️

Video hosting with their own hands

This article is about some technical aspects of the implementation of a free service for downloading, storing and viewing videos. The questions of setting up server software will be discussed, examples of commands for video conversion and examples of PHP code will be given.

With the introduction of HTML5 standard support in many browsers, it has become possible to embed a video player using the video tag. Each browser supports a specific set of codecs and containers. This support is very well described at http://diveintohtml5.org/video.html#what-works .

One of the main requirements for the system was support for Apple devices (iPhone, iPad, iPod). Due to the fact that these devices support online video in a single format - MP4 and do not have the ability to use Flash-player, it was originally decided to take as a basis a universal MP4-container (H.264 video and AAC audio). Encoding uses free implementations of these codecs libx264 and libfaac. It was decided to compensate for the lack of support for these formats in other browsers using a Flash player, which connects automatically if the user's browser does not support the video tag, or if support is not possible because the browser does not support MP4 video.

Architecture


The system architecture is quite simple and includes 2 types of servers:

image
')
The main workhorses for content delivery are file servers. The idea is to move the file from the main server to the file server as soon as possible after the conversion in order to avoid a load jump on the network interface in case of downloading a popular video. In order to determine on which server the particular video is currently located, the database has a linking table videos_servers. On all file servers and the conversion server, a module for streaming video is installed. To move files between servers using the NFS protocol.

The conversion queue is organized using the beanstalkd queue server ( http://kr.github.com/beanstalkd/ ). Tests show that it is possible to run 30 workers on a six-core server. 30 users will be able to simultaneously convert video without sacrificing overall system performance (the page generation time on the web server side remains acceptable). Tests with a large number of workers were not conducted, but there is a good supply of power and, if necessary, the number of workers can be increased.

Server software


Debian Lenny is installed on the conversion server and on all file servers.

Video processing software

To convert video to MP4 format, the most popular solution currently used is ffmpeg ( http://www.ffmpeg.org/ ). ffmpeg does an excellent job with video conversion in a wide variety of formats and can use several processor cores in a multi-core system. For post-processing, we use the wonderful MP4Box utility from the gpac package ( http://gpac.sourceforge.net/ ). Post-processing is necessary because ffmpeg places “moov-atoms” (meta-information about the video) at the end of the file, however, in order for the user to be able to watch the video without waiting for it to fully load, these atoms must be at the beginning of the file. MP4Box moves them to the beginning and, in addition, brings the file into compliance with all standards, makes it suitable for streaming through the corresponding module.

 $ ffmpeg -vpre videobam -y -i input.avi -s 320x240 -vcodec libx264 -acodec libfaac -threads 0 -ab 64k -b 400k -bt 500k -g 24 -r 24 temp.mp4
 $ Mp4box -add temp.mp4 output.mp4

Focus on the -g 24 option. It determines how many frames each new keyframe will be saved (keyframe). The presence of key frames is necessary so that the user can scroll through a long movie without waiting for it to fully load. This feature is implemented using the broadcast module. The client (browser or Flash player) sends the GET parameter start to the web server, which is processed by the translation module and means the number of seconds from which to start playback.

 GET /output.mp4?start=856.733 HTTP / 1.1

In addition, the -threads 0 parameter will significantly increase the conversion speed by telling the program to automatically determine the number of processor cores and use them in the process. It is important to specify the required number of frames -r 24 . We had problems with some videos due to an inadequately high number of frames per second (mostly screencasts), for which the conversion time was completely irrelevant to the duration of the movie.

For each video, screen shots are taken at specific points in time so that the user can briefly assess the content of the video. An example of such pictures can be seen at the bottom of the page http://videobam.com/tour . ffmpeg is not able to take these pictures quickly (he rewinds the video to the right moment and only then takes the picture). For quick snapshots, we use the mplayer utility ( http://www.mplayerhq.hu/ ), which takes pictures almost instantly when moving around the file using keyframes.

 $ mplayer -ss 00:00:04 -sstep 12 -frames 16 -vo jpeg: outdir = / tmp / pictures / -nosound output.mp4

It should be noted that all software is compiled manually from source codes (it is cloned from the corresponding version control systems or fresh builds are used). It is very important to use the newest versions of the stable branches, since it takes a long time from the moment any bug is fixed before these fixes get into the package of your chosen Linux distribution. In particular, we faced the problem of stuttering sound when converting some QuickTime clips to MP4 format. The problem was successfully solved by installing the latest version of libfaac and libfaad libraries.

Server modules

Note: to build the h264 module, you may need to apply the http://pastie.org/1405286 patch.

 $ cd nginx-0.8.53
 $ ./configure --add-module = .. / nginx_mod_h264_streaming-2.2.7 / --add-module = .. / ngx_http_secure_download /

Streaming video is provided by the h264 module for the nginx web server ( http://h264.code-shop.com/ ). Setting up this module is very simple:

/usr/local/nginx/conf/nginx.conf
 location ~ \ .mp4 $ {
   mp4;
 }

Restart the server and try to load the movie from the 10th second:

 $ wget -O temp.mp4 “http://videobam.com/test.mp4?start=10.0”

To protect against link copying (hotlinking), we use the HTTP Secure Download module ( http://github.com/replay/ngx_http_secure_download ). It allows you to encode a link to a video file using the salt set in the settings.

/usr/local/nginx/conf/nginx.conf
 location ~ * / videos {
   secure_download on;
   secure_download_path_mode file;
   secure_download_secret saltsal salt $ remote_addr;

   if ($ secure_download = "-1") {
       rewrite /expired.html break;
   }
   if ($ secure_download = "-2") {
       rewrite /bad_hash.html break;
   }
   if ($ secure_download = "-3") {
       return 500;
   }

   mp4;
   rewrite ^ (. *) / [0-9a-zA-Z] * / [0-9a-zA-Z] * $ $ 1 break;
 }

The download link is generated as follows:

 public function secure_url ($ url)
 {
   $ ts = time () + 3600;
   $ ts_in_hex = dechex ($ ts);
   $ secret = 'saltsaltsalt'.  $ _SERVER ['REMOTE_ADDR'];
   $ hash = md5 ($ url. '/'. $ secret. '/'. $ ts_in_hex);
   return $ url.  '/'.  $ hash.  '/'.  $ ts_in_hex;
 }

NFS and autofs

Autofs is installed on the conversion server to work with file servers. It mounts the necessary file servers on request. All NFS partitions are mounted in “soft” mode (soft mode) in order to avoid the hangup of the copy process in case the file server fails.

/etc/auto.storage
 0: / var / www / shared / local_storage
 1 -fstype = nfs, rw, async, soft, intr, timeo = 20, rsize = 64000, wsize = 64000 f1.videobam.com:/var/storage
 2 -fstype = nfs, rw, async, soft, intr, timeo = 20, rsize = 64000, wsize = 64000 f2.videobam.com:/var/storage
 3 -fstype = nfs, rw, async, soft, intr, timeo = 20, rsize = 64000, wsize = 64000 f3.videobam.com:/var/storage
 4 -fstype = nfs, rw, async, soft, intr, timeo = 20, rsize = 64000, wsize = 64000 f4.videobam.com:/var/storage

The structure of files and folders on all servers is identical, so working with file servers is carried out transparently by substituting the server identifier into the path template. It is important to remember about the limitations of the ext3 file system on the number of files and folders in a specific directory, all videos are stored in a directory like videos / a / ab / video.mp4, where “a” and “ab” are the first letters in the video title.

Client part


As mentioned earlier, we use VideoJS ( http://videojs.com ) to play and style HTML5 video. In addition, VideoJS performs a “smarter” rollback to the Flash player (if there is no video file supported by the browser in the source list). Flowplayer ( http://flowplayer.org ) is used as a Flash player.

Subject references


Software:

beanstalkd kr.github.com/beanstalkd
VideoJS videojs.com
flowplayer flowplayer.org
ffmpeg www.ffmpeg.org
mplayer www.mplayerhq.hu
gpac (MP4Box) gpac.sourceforge.net
nginx 0.8.53 nginx.org/en
nginx h264 streaming module h264.code-shop.com
nginx http secure download github.com/replay/ngx_http_secure_download
nginx upload progress module github.com/masterzen/nginx-upload-progress-gimodule

Additional materials:

diveintohtml5.org/video.html
rob.opendot.cl/index.php/useful-stuff/ffmpeg-x264-encoding-guide
sites.google.com/site/linuxencoding/x264-ffmpeg-mapping
x264dev.multimedia.cx
rodrigopolo.com/ffmpeg/cheats.html
e-mats.org/2010/01/fixing-stuttering-audio-with-ffmpeg-and-quicktime
www.videohelp.com/tools/mp4box

Source: https://habr.com/ru/post/111249/


All Articles