VLC WMV Streaming

Introduction
Encoding Streamable WMVs with ffmpeg
VLC Stream Commands
Caveat - bitrate override
Caveat - Swapped Stream
Conclusion
Introduction
Having had to figure out a decent video streaming solution, I opted to go with VLC, as it is one of the best options for streaming, and WMVs for easier cross-platform support. I, of course, very much dislike the WMV format, but being that I had to reach the maximum possible viewers as possible, I was forced to use it.
All this information was acquired through ardious trial and error, as much of the documentation available is either non-existant, or very much incomplete. To be more specific, documentation regarding streaming with VLC is decent, however very much lacking, and on streaming WMVs in general, with or without VLC, is also almost non-existant.
All this information was acquired through ardious trial and error, as much of the documentation available is either non-existant, or very much incomplete. To be more specific, documentation regarding streaming with VLC is decent, however very much lacking, and on streaming WMVs in general, with or without VLC, is also almost non-existant.
Encoding Streamable WMVs with ffmpeg
To be able to stream, we, obviously, will first need a compatible WMV. Rather than use a basic test example, I opted to use ffmpeg to encode my own WMV to my own specifications. These specifications are:
Video Codec: wmv2 Resolution: 640x360 Bitrate: 768kb FPS: 29.97 Audio Codec: wmav2/wma2 Bitrate: 96kb Sample Rate: 44100 Channels: 2(stereo)To adhere to these specifications, the ffmpeg command is:
ffmpeg -i input.avi -vcodec wmv2 -b 768k -r 29.97 -acodec wmav2 -ar 44100 -ac 2 -ab 96k -y output.wmvOnce you issue this command on a video file, you should get somewhat of the following results:
[user@host Test Clips]$ ffmpeg -i "input.avi" -vcodec wmv2 -b 768k -r 29.97 -acodec wmav2 -ar 44100 -ac 2 -ab 96k -y "output.wmv"
FFmpeg version 0.5, Copyright (c) 2000-2009 Fabrice Bellard, et al.
Input #0, avi, from 'input.AVI':
Duration: 00:00:11.65, start: 0.000000, bitrate: 10065 kb/s
Stream #0.0: Video: mjpeg, yuvj422p, 640x480, 20 tbr, 20 tbn, 20 tbc
Stream #0.1: Audio: pcm_u8, 11024 Hz, mono, s16, 88 kb/s
Output #0, asf, to 'output.wmv':
Stream #0.0: Video: wmv2, yuv420p, 640x480, q=2-31, 768 kb/s, 90k tbn, 29.97 tbc
Stream #0.1: Audio: wmav2, 44100 Hz, stereo, s16, 96 kb/s
Stream mapping:
Stream #0.0 -> #0.0
Stream #0.1 -> #0.1
Press [q] to stop encoding
Warning, using s16 intermediate sample format for resampling
frame= 348 fps=124 q=12.7 Lsize= 1451kB time=11.61 bitrate=1023.6kbits/s
video:1276kB audio:136kB global headers:0kB muxing overhead 2.706774%
[user@host Test Clips]$
Upon completion you should now have a wmv that should work with VLC for streaming.
VLC Stream Commands
Now that we have our .wmv ready, go to the directory containing it and issue the following:
vlc -I dummy -I http --http-host 192.168.180.114:8084 --loop -vvv \
output.wmv --sout-transcode-audio-sync --sout-transcode-deinterlace --sout \
'#gather:std{access=http,mux=asf,dst=192.168.180.114:8083}' \
--sout-mux-caching=20480 --sout-keep --sout-asf-bitrate-override=428000 \
--file-caching 1200
A run-down of the options are:
-I dummy - This sets it so that the control interface is a dummy. Not required.
-I http - This is the http control interface, extremely useful and excellent for control.
Not required.
--http-host 192.168.180.114:8084 - This is the address and port for the http control.
Not required.
--loop - This just tells the playlist to loop. Not required.
-vvv - Extremely verbose output - good for debugging. Not required.
output.wmv - Just the video input file. Obviously required.
--sout '#gather:std{access=http,mux=asf,dst=192.168.180.114:8083}' - Sadly, I
forget the exact definitions of some of these, however: access=http is the
output stream type, it can also be rdp. mux=asf is the container muxer format
(or something), which is .asf. dst=192.168.180.114:8083 is our destination
address, which is port 8083 of the same host machine.
--sout-asf-bitrate-override=428000 - This is one of the most important options,
without it many problems can arise, as covered below.
Be sure to replace 192.168.180.114 with the IP address of the machine the vlc server is running on. You should then be able to access the HTTP control interface at http://192.168.180.114:8084 and the actual video stream at 192.168.180.114:8083.
Caveat - bitrate override
A problem that was found shortly after having the stream up was that Windows Media Player 10(and below, I presume) would take an extremely long time to buffer. In contrast, Windows Media Player 12 worked perfectly. This is, presumably, due to improved bitrate calculations and checking. mplayer-plugin and the VLC Internet Plug-In, on Linux, Mac, and Windows, worked perfectly, of course.
Presumably, this is due to Windows Media Player 10 somehow estimating an erroneous bitrate in relation to the streaming file size, causing it to continue to fill its buffer, taking minutes to get to a point where it believes it can play the video.
After some troubleshooting, the VLC option "--sout-asf-bitrate-override" was discovered, allowing the specification of the bitrate, rather than having it read from the media file, or guessed at by the client. The bitrate is then sent to the bitrate of the media file in bytes.
A sample command that executes this fix would be:
To find the bitrate from KB(kilobytes), the KB must by multiplied by 1024. For example, if the combined bitrate in KB of the media is 535KB, we would multiply that by 1024, getting the end value of 547840.
Presumably, this is due to Windows Media Player 10 somehow estimating an erroneous bitrate in relation to the streaming file size, causing it to continue to fill its buffer, taking minutes to get to a point where it believes it can play the video.
After some troubleshooting, the VLC option "--sout-asf-bitrate-override" was discovered, allowing the specification of the bitrate, rather than having it read from the media file, or guessed at by the client. The bitrate is then sent to the bitrate of the media file in bytes.
A sample command that executes this fix would be:
vlc -I dummy --loop -vvv output.wmv --sout \
'#gather:std{access=http,mux=asf,dst=192.168.180.114:8083}'\
--sout-asf-bitrate-override=428000 --sout-mux-caching=5000\
--sout-keep --file-caching 1200
To find the bitrate from KB(kilobytes), the KB must by multiplied by 1024. For example, if the combined bitrate in KB of the media is 535KB, we would multiply that by 1024, getting the end value of 547840.
Caveat - Swapped Stream
Another problem that I ran into was that some video encoding software would swap the audio and video stream's locations, making a very non-standards video. That is to say, stream #0.0 should almost always be the video stream, with the following streams(e.g., #0.1 and onward) being audio, subtitles, etc.. The non-standards compliant video software would make #0.0 the audio stream and #0.1 the video stream.
To be more specific of how it should be encoded:
You have an encapsulation format(.wmv, .avi, .mp4, etc.) and inside of that there are various streams, such as the following:
As a minor note, subtitle streams can also be encapsulated, usually at a greater offset than video or audio streams(around Stream #1.0(or 10), or something similar).
To be more specific of how it should be encoded:
You have an encapsulation format(.wmv, .avi, .mp4, etc.) and inside of that there are various streams, such as the following:
Stream #0.1(or 0) - Video: wmv2 Stream #0.2(or 1) - Audio: wmav2Then, optionally, for some encapsulation formats, you can have additional following streams in a manner such as:
Stream #0.3(or 2) - Audio: wmav2 Stream #0.4(or 3) - Audio: wmav2These additional audio streams would be alternative audio that you could use to the video - these could be commentary, translations, etc.
As a minor note, subtitle streams can also be encapsulated, usually at a greater offset than video or audio streams(around Stream #1.0(or 10), or something similar).
Conclusion
Although this was very much a headache to implement, as there were many problems both server and client side, it turned out to work fairly well.
However, I received much feedback with questions of "why not use flash?", to which I respond:
Although it is true that Flash is very much universally supported, I find it to be extremely inefficient for video. It may be true that sites such as YouTube, metacafe, etc. have utilized Flash to be able to deliver lots of content with ease, however these sites do not work efficiently with any computer that is older than 5 years old. The reason being is that flash, although it is very useful, runs video very poorly. For example, if you try to run a video that is 720p or 1080p, it will generally take up a great deal of processing power to view - however, if the same video is viewed in a format such as h264, it will display with far less processing and will also be viewable on even outdated machines. To put it bluntly, Flash was never meant for displaying video, much less streaming video, and although it does work, it does it in a very inefficient manner.
However, I received much feedback with questions of "why not use flash?", to which I respond:
Although it is true that Flash is very much universally supported, I find it to be extremely inefficient for video. It may be true that sites such as YouTube, metacafe, etc. have utilized Flash to be able to deliver lots of content with ease, however these sites do not work efficiently with any computer that is older than 5 years old. The reason being is that flash, although it is very useful, runs video very poorly. For example, if you try to run a video that is 720p or 1080p, it will generally take up a great deal of processing power to view - however, if the same video is viewed in a format such as h264, it will display with far less processing and will also be viewable on even outdated machines. To put it bluntly, Flash was never meant for displaying video, much less streaming video, and although it does work, it does it in a very inefficient manner.
0.0062260627746582 µs