Encoding Stream Video

Update:

To make things easier I have made some Command Prompt / Bash scripts that use all the best practices and commands described on this guide but way better, click here to see the BinKit 2.0 and how can simplify your life.

Guide:

This is a deep study and a guide on how to encode video for pseudo-streming on the web, I’m following the same specs that YouTube use doing some reverse engineering and analyzing the video encoded by YouTube today.

Fisrt of all you have to know that a video online has many many versions and many files, each version is encoded to fit the needs of different bandwidths and devices, in this case I’ll show the most common video versions and files used in a YouTube video:

  • 240p – A video version designed to fit a bandwidth of 256Kbps aprox, it has 432x240px for widescreen video (16:9) and 320x240px for standard video (4:3) aspect ratio.
  • 360p – A video version designed to fit a bandwidth of 768kbps to 1Mbps, it has 640x368px for widescreen video and 480x368px for standard video, it is the default format that YouTube gives today.
  • 480p – A video version designed to deliver DVD like quality to de web, it became popular on the web when YouTube realize that HD format was not really ready for everyone on the web, it has 848x480px for widescreen video and 640x480px for standard video and uses an average bitrate of 768Kbps to 1768Kbps.
  • 720p – The typical HD version, it has 1280x720px for widescreen and it doesn’t exist in the standard video size, it use an average bitrate of 2Mbps and a max bitrate of 6 to 8Mbps.
  • iPhone/iPad/iPod Touch – A video version designed to run on modern mobile devices, it is encoded in a way that doesn’t require huge CPU power to be decoded, it has 480x272px for widescreen video and 480x368px for standard video and an average bitrate of 400Kbps to 800Kbps.
  • Thumbnails – Youtube generate some JPG images from the video in order to appear as thumbnails for the video.
  • Captions – A file that contains the captions or subtitles for the video, the common format for JW Player is an XML file and there are several utilities online to convert an SRT subtitle format to this XML format.

The Strem Video Player plug-in for WordPress use the JW Player where you can switch between only two formats, a low bandwidth format and a high quality format, you have to decide which low and high quality formats fit your audience, on the following example I’ll use the 240p version to reach more users, the 480p to give good quality but be able to fit a flawless playback on 1Mbps connections, I will also make 10 snapshots of the video and will convert a SRT captions file to XML format.

Notice that you can encode your video using any tool available for encoding to FLV and MP4, but also notice that you have to encode your video to get H.264 video and AAC audio on a FLV or MP4 file AND for the pseudo-streming technique the FLV video file has to have his metadata included and a key frame each second or each 3 seconds at most, this is mandatory for the pseudo-streaming.

For this guide I use FFmpeg which is a command line video encoding software, the main reasons to use FFmpeg are quite simple, it runs on Windows, Linux and Macintoch, it’s fast and the most important, it is Free Software (free = libre).

FFmpeg team only deliver the source code of the project so you need to compile it before using it or find a place online to download a compiled version, because I know it is not that easy I have done some compilations that run on Windows, Linux and Macintoch, you can download and install them here, also NOTICE that I use an X264 video encoding preset called iphone that it’s only available on my custom FFmpeg build, if you are not using my custom version you have to download and put it inside the folder where are your other ".ffpreset" files, typically on "C:usrlocalshareffmpeg" for Windows or "/usr/local/share/ffmpeg" for Linux and Macintosh, you can download the iphone preset here.

I’ll use a pice of video of the computer animated film by the Blender Institute, Big Buck Bunny as the input for this encoding; you can download the source here:

http://rodrigopolo.com/wp-content/uploads/video/BigBuckBunny/Input-For-Encoding.mp4

You can put your video on a folder for the encoding, I’ll make a folder called "encoding" on my desktop, then I use my "Terminal" or "Command Prompt" and get to my folder, if you don’t know how to do this I’m sorry to tell you this guide isn’t for you.

The most important thing is to know your input frame rate and aspect ratio, you have to encode your video trying to get the closest to your source specs, also notice that to achieve very good quality and low bitrate it is a best practice to ensure that the width and height of your video is evenly divisible by 16, to know your source specs you can use FFmpeg by only giving the input flag:

Ffmpeg -i Input-For-Encoding.mp4

You will get something like the following


Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'Input-For-Encoding.mp4':
Duration: 00:01:19.04, start: 0.000000, bitrate: 6109 kb/s
Stream #0.0(eng): Video: h264, yuv420p, 1280x720, 24.00 tb(r)
Stream #0.1(eng): Audio: aac, 48000 Hz, stereo, s16
At least one output file must be specified

You can see that the input has streams, the audio and video stream have some specs as codec, format, size and frame rate and the audio have codec, hertz, number of channels and bits.

Some video sources are interlaced, the encoding we are using doesn’t work well if the video is interlaced so we have to deinterlace the video if it’s necessary, to know if a video it’s interlaced the most practical way it’s to make an snapshot of your video, this is the command I use to take a PNG snapshot of a video:

ffmpeg -i Input-For-Encoding.mp4 -ss 10 -vframes 1 -an -f image2 snapshot.png

You can change the "-ss" flag to change the point in time where you want to take the snapshot, after seeing your snapshot check if it has some lines on it, this lines are more visible when the video has something moving fast, if it is interlaced you have to add the "-deinterlace" flag to your encoding command.

The first encoding I’ll do is the iPhone encoding, to achieve very good quality I’ll use a two pass encoding with the same X264 preset, notice that the input video has 24fps but in some cases you’ll see 29.97fps or 23.976fps, to achieve frame rate accuracy and avoid audio sync issues it is recommended to use type "30000/1001" for 29.97fps and "24000/1001" for 29.976fps in your "-r" frame rate flag.

Also notice that I’m using 480x272px dimension to fit on the iPhone screen, a 16:9 video with the max width of 480px have a video dimension of 480x270px BUT this size doesn’t fit the evenly divisible by 16 rule, that’s why it is mandatory to use the aspect ratio flag so when the iPhone playback the video it change automatically the size of the video from 480x272px to 480x270p.

Another important flag is the "keyframe flag" which I always try to fit the frame per second, in this case 24.

WARNING: A flag I use many times is the Threads flag, be careful with this flag, I have an Intel i7 procesor so I decided to use 16 threads but with a Intel Quad Core I can only achieve 8 threads, the more threads the faster you get your encoding done, if you put more threads than your CPU can handle FFmpeg will return an error.

Because I’m using a "two pass" encoding I have to encode the video twice and of course typing two different encoding commands, you can "concatenate" both lines using "&&" between the two encoding commands, something like "ls && clear" or "dir && cls", here are my two encoding lines for iPhone encoding:

ffmpeg -y -threads 8 -i Input-For-Encoding.mp4 -s 480x272 -aspect 16:9 -r 24 -vcodec libx264 -pass 1 -b 448k -maxrate 752k -bufsize 1504k -g 24 -vpre iphone -f mp4 -an 01-iPhone.mp4

ffmpeg -y -threads 8 -i Input-For-Encoding.mp4 -s 480x272 -aspect 16:9 -r 24 -vcodec libx264 -pass 2 -b 448k -maxrate 752k -bufsize 1504k -g 24 -vpre iphone -acodec libfaac -ac 2 -ar 44100 -ab 96k -f mp4 01-iPhone.mp4

And for the 240p, 360p, 480p and 720p encoding I use this commands:

# 01-iPhone
ffmpeg -y -threads 8 -i Input-For-Encoding.mp4 -s 480x272 -aspect 16:9 -r 24 -vcodec libx264 -pass 1 -b 448k -maxrate 752k -bufsize 1504k -g 24 -vpre iphone -f mp4 -an 01-iPhone.mp4

ffmpeg -y -threads 8 -i Input-For-Encoding.mp4 -s 480x272 -aspect 16:9 -r 24 -vcodec libx264 -pass 2 -b 448k -maxrate 752k -bufsize 1504k -g 24 -vpre iphone -f mp4 -acodec libfaac -ac 2 -ar 44100 -ab 96k 01-iPhone.mp4

# 240
ffmpeg -y -threads 8 -i Input-For-Encoding.mp4 -s 432x240 -aspect 16:9 -r 24 -vcodec libx264 -pass 1 -b 224k -maxrate 704k -bufsize 1408k -g 24 -vpre fastfirstpass -an 02-240.flv

ffmpeg -y -threads 8 -i Input-For-Encoding.mp4 -s 432x240 -aspect 16:9 -r 24 -vcodec libx264 -pass 2 -b 224k -maxrate 704k -bufsize 1408k -g 24 -vpre hq -acodec libfaac -ac 2 -ar 44100 -ab 32k 02-240.flv

# 360
ffmpeg -y -threads 8 -i Input-For-Encoding.mp4 -s 640x368 -aspect 16:9 -r 24 -vcodec libx264 -pass 1 -b 480k -maxrate 768k -bufsize 1536k -g 30 -vpre fastfirstpass -an 03-360.flv


ffmpeg -y -threads 8 -i Input-For-Encoding.mp4 -s 640x368 -aspect 16:9 -r 24 -vcodec libx264 -pass 2 -b 480k -maxrate 768k -bufsize 1536k -g 30 -vpre hq -acodec libfaac -ac 2 -ar 44100 -ab 128k 03-360.flv

# 480
ffmpeg -y -threads 8 -i Input-For-Encoding.mp4 -s 848x480 -aspect 16:9 -r 24 -vcodec libx264 -pass 1 -b 1072k -maxrate 1616k -bufsize 3232k -g 24 -vpre fastfirstpass -an 04-480.flv

ffmpeg -y -threads 8 -i Input-For-Encoding.mp4 -s 848x480 -aspect 16:9 -r 24 -vcodec libx264 -pass 2 -b 1072k -maxrate 1616k -bufsize 3232k -g 24 -vpre hq -acodec libfaac -ac 2 -ar 44100 -ab 128k 04-480.flv

# 720
ffmpeg -y -threads 8 -i Input-For-Encoding.mp4 -s 1280x720 -aspect 16:9 -r 24 -vcodec libx264 -pass 1 -b 1904k -maxrate 3088k -bufsize 6176k -g 24 -vpre fastfirstpass -an 05-720.flv

ffmpeg -y -threads 8 -i Input-For-Encoding.mp4 -s 1280x720 -aspect 16:9 -r 24 -vcodec libx264 -pass 2 -b 1904k -maxrate 3088k -bufsize 6176k -g 24 -vpre hq -acodec libfaac -ac 2 -ar 44100 -ab 128k 05-720.flv

IMPORTANT: in order to use this FLV videos with the pseudo-stream technique you have to inject the video metadata on the FLV, for this task I recommend FLVMeta which is included in the FFmpeg installation on this site, you can also download from the official FLVMeta site by clicking here.

The command for inject the FLV Metadata is very very easy, it requires only two parameters, the input and the output file without any flag, here is the command:

flvmeta input.flv injected_output.flv

I’ll inject the metadata in all my encoded files:

flvmeta 02-240.flv 02-240in.flv
flvmeta 03-360.flv 03-360in.flv
flvmeta 04-480.flv 04-480in.flv
flvmeta 05-720.flv 05-720in.flv

Now let’s make 10 snapshot of the video, a very easy way to do this it’s to use FFmpeg to export the video to an image sequence AND change the frame rate to a very low bitrate, I have done an equation to get a low frame rate that make the amount of snapshot I want, I divided the length of the video in seconds into the amount of frames I want and then I divided 1 into that result, the result of that it’s the frame rate for the input, so for this video I have a duration of "00:01:19.04" which are 76.04 seconds, so 76.04/10 = 7.604 and 1 / 7.604 = 0.1315097317201473… here is the equation:

1/(76.04/10) = 0.1315097317201473

Here is the command for the snapshots, notice that you can choose between JPG or PNG by just changing the file extension on the command:

# PNG
ffmpeg -i Input-For-Encoding.mp4 -r 0.1315097317201473 -s 480x270 -an -f image2 thumb_%d.png

# JPG
ffmpeg -i Input-For-Encoding.mp4 -r 0.1315097317201473 -s 480x270 -an -f image2 thumb_%d.jpg

Now, for the SRT captions (subtitles) you can make your own captions with Subtitle Workshop for Windows or this other tools for Linux an Macintosh and save your captions as SRT format, then you can use my SRT2XML conversion utility online http://tools.rodrigopolo.com/srt2xml/ to make it compatible for JW Player.

Ok, so we have the needed files for a video publishing with the Stream Video Encoder, as I said before I’ll only publish the iPhone version with the 240p and the 480p version of the video, this are the file I’m going to upload to my server via FTP:

  • thumb_5.jpg – the thumbnail or image preview of the video.
  • 01-iPhone.mp4 – the Android, iPhone/iPad/iPod Touch version of the video.
  • 02-240in.flv – the injected 240p version of the FLV video.
  • 04-480in.flv – the injected 240p version of the FLV video.
  • captions.xml – the captions file

Notice that WordPress can’t handle some uploads because the file types so I use FTP for the uploading, I recommend to use a folder for each video you upload, now that you have all your video files on your server create or edit any post or page on WordPress and with the Stream-Video-Player tag generator browse for your files until you have something like this:

svpsvp

So that’s it, now you have a video that can run on an iPhone/iPad/iPod Touch and also on any computer, it has subtitles (captions) and you can go to any time on the video random because the pseudo-streming.

If you want to embed subtitles for the iPhone you can use Subler which works great for me, the only issue is that only runs on OS X, there is also Jubler which is a multiplatform solution but I haven’t tasted yet, here are the links:

http://code.google.com/p/subler/

http://www.jubler.org/

Do you have your video/s already encoded using H.264 and AAC but in MP4? Don’t worry, can change the video encapsulator with FFmpeg without reencoding your video using the following command:

ffmpeg -i input_video.mp4 -vocdec copy -acodec copy output_video.flv

Then just add the metadata with FLVMeta

flvmeta input.flv output.flv

So this is it, hope this little guide help you encode and share your videos online with the Stream Video Player!


26 Responses to Encoding Stream Video

  1. Pingback: Tweets that mention RodrigoPolo.com - Encoding Stream Video -- Topsy.com

  2. Michael says:

    hello,

    I have a problem.
    With ur plugin and ur video player.
    i have videos, I can move and others dont !
    Where does the problem?

    hope you understand the problem.
    there are flv videos I can progress and other I cant ! :(

  3. michael says:

    functiona
    gracias por todo

    pero es complicado cuando tiene 400 flv…
    con la lina de comando. ^^

    • Rodrigo Polo says:

      De hecho en Linux/Macintosh si instalas el FLVMeta adecuadamente para que corra desde cualquier path puedes crear un script SH para que haga la conversión de todos los FLVs en una carpeta.
      1-crea un archivo .sh en la carpeta donde tienes tus FLVs
      2-copia el código de este URL a ese .sh http://ffmpeg.pastebin.com/neFXdUNN
      3-asignale los permisos de ejecución al .sh (chmod 775 ./archivo.sh)
      4-ejecuta el script .sh escribiendo ./archivo.sh estando en el path donde se encuentra.

    • Rodrigo Polo says:

      Olvidé comentar que también en Windows puedes crear un archivo .bat en la carpeta donde tienes tus FLVs y copiar esta línea
      for %%a in (“*.flv”) do flvmeta “%%a” “%%~na.injected.flv”

      Es requerido que el FLVMETA esté instalado en un path de sistema.

  4. Larry says:

    Is there any way to get the logo in the player to stay “on” during entire video? I see it as a feature in the JW Player, but can’t figure out where this would go in your scripts. They have a call like: logo.hide (“false”).

    This would be a great feature to add in the settings admin.

  5. Pingback: n900 ffmpeg flv | Romis

  6. Mike says:

    Thank-you very much. This was a very straightforward tutorial. I followed the steps as you described, and everything worked well.

    Thanks again for you hard work on this plugin, + the great site for explaining how to use it!

    Mike.

  7. GFX Sky says:

    WOW, it’s awesome.
    I’ve searched for something like this for a long time. I’m really happy because i finally found your site.
    This guide help me a lot.

    Thanks again.

    GFX Sky,

  8. Luis says:

    Hey que tal, Rodrigo!

    Primero que nada, muchas gracias por el excelente plugin para WP. Me funciona super bien, pero tengo una pregunta.

    Cómo hago para poder hacer streaming de un video que está almacenado en Amazon S3? Necesito cambiar algo en los settings?

    Te agradezco por tu tiempo y cualquier información que puedas darme al respecto.

    Saludos!

  9. Sven says:

    Hey,

    I encoded my videos to stream them on my website using TMPGEnc Xpress 4.0.

    My problem is my videos won’t stream at all. They buffer completely before they start streaming.

    I tried multiple settings, downloaded a file from youtube (that plays fine on my site) and used that settings… Still not working.

    Any idea what could be the reason (Streaming by http)?

    (can post file-info or upload the video if this helps finding the reason)

    What about the keyframe every second? Which frames are that? The I-Frames?
    If I got Keyframes only after a minute won’t this then work at all or just limit the parts to skip while streaming?

    Please help you seem to know about streaming and I did not find anyone who is able to help me until now.

  10. Sven says:

    Found the reason. Sorry bothering you but looked for the solution since months….

    You have to set the mp4 container to “ISMA Compatible”

    Anyway, Thanks!

  11. Pingback: WP, encoding streaming video by FFMpeg on Windows at NetSys.HK

  12. Jose says:

    I can’t seem to see the folder structure when I use “media library”

    http://img.photobucket.com/albums/v652/jtadeo/streamissue.jpg

  13. Pingback: links for 2010-12-08 | Ronaldo Richieri

  14. viorel says:

    hi i found a tool for enconding that user ffmpeg in ubuntu

    WinFF

    i could modifi the setting but no understend so good the comand line

    i wander if you could help me to make a preset for the program
    to make first pas and the second pas for encoding + some thumbs

  15. viorel says:

    Hi rodrigo you do a great job with this plugin.

    Onli thing that is missing is a multi encoder tool

    i found on google a free video encoder

    wil be great that you make some presets for that tool
    i was enable to succes to make the encoder in 2 steep and add the flvmeta

    can make the preset im sure that alot of people would be hapy to use

    http://winff.org/html_new/

    some plugin feature

    * Easy to use interface.
    * Fast (Winff does not hinder FFmpeg in anyway).
    * High quality output.
    * Converts multiple different files all to the same format at once.
    * Convert video to audio.
    * Convert between audio formats.
    * No external codecs needed.
    * Includes a variety of preset conversion settings for common formats and devices.
    * Preset conversions can be created to encode to any format FFmpeg supports.
    * Easy access to common conversion options such as bitrate, frame size, frame rate.
    * Specify additional command line parameters for advanced users (options button).
    * Easily change FFmpeg versions.
    * Supports FFmpeg’s multi threading for dual core processors
    * Multilingual, available in over 10 languages

  16. meyourfriend says:

    Hello,

    I did not edit any of my .flv files and they work perfectly with the plugin, which is just wonderful.

    Although when attempting to play on an iphone/ipod/ipad, the video just appears with a ‘grey’ quicktime skin that has a cross through the play button. I have even uploaded an .mp4 video in the ‘iphone video’ part when inserting the video.

    I spent 2 hours looking for a solution and have not seen any others with the same issue.

    Thanking you in advance for the plugin and your update.

  17. Pingback: film test | website van Huub van der Heide

Back to Top ↑