This worked for me:
1. I edited the SMIL example in the FLVPlayback 2.5 doc to point to the vod app and to the sample files that install with the vod app. I saved the file as "test.smil":
<meta base="rtmp://localhost/vod/" />
<video src="mp4:sample1_150kbps.f4v" system-bitrate="150000"/>
<video src="mp4:sample1_500kbps.f4v" system-bitrate="500000"/>
<video src="mp4:sample1_700kbps.f4v" system-bitrate="700000"/>
2. I created an AS3 file in Flash, added the FLVPlayback 2.5 component, and saved the file to the same folder as the test.smil file.
3. In the Component Inspector I set the source parameter to test.smil.
Ok, we'll get this dynamic streaming thing working by hook or by crook! (Whatever that means)
Jody, I followed your very easy-to-follow instructions above, and I am indeed seeing video playing (the lovely helicopter footage).
However, it still doesn't seem to be swapping video files when the bandwidth changes.
If I restrict the bandwidth (using NetLimiter) way down to, say, 2Kbps, I don't see the quality of the video change. After about five seconds of playing, the video starts stopping and starting, (barber pole and all), but I don't see things switching to a more highly compressed video file.
What am I missing?
i spoke with Brad Outlaw who created the DynamicStream class. he said all you need to do is point to a propertly formed SMIL file from the source property of the component. he also said your issue could be attributed to a bug he found in the component. he's planning to push an update (126.96.36.199) very soon to www.adobe.com/fms_tools.
seems like we're dealing with a bug...
Can you see if Brad can recommend the best way to test the Dynamic Streaming Class he created? Would it be by using NetLimiter or similar? The problem may be in the testing.
I'm sure he's come up with a way to test multiple bandwidths in a typical authoring environment.
There are a number of ways you can test it. NetLimiter is one option. With that you can throttle back the bandwidth at an OS driver level and properly test the behavior of maxBytesPerSecond. Some of the more advanced scenarios involve things like Shunra (which is expensive and cumbersome to set up but good if someone has access to it). The simplest test case would be to use the setBandwidthLimit method on the DynamicStream class. Since it overrides the values returned by maxBytesPerSecond, you can arbitrarily assign values there more easily. The only caveat to the setBandwidthLimit approach is that if your actual maxBytesPerSecond is lower than the values you set for bandwidth limit, maxBytesPerSecond takes precedence.
Could you ask Brad if he can confirm that Dynamic Streaming works with SMIL files and H.264/AAC encoded content in MP4 format? I was wanting to rebuild our video player using his new FLVPlayback 2.5. component but I have been frustrated to the point that I'm ready to give up.
We use Limelight as our CDN and I have placed a SMIL file on our HTTP progressive download server "x.com" at the following location:
Here are the contents of the SMIL:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE smil PUBLIC "-//W3C//DTD SMIL 2.0//EN" "http://www.w3.org/2001/SMIL20/SMIL20.dtd">
<meta base="rtmp://x.com/myapp/" />
<video src="mp4:test/waf_2386_preview_180p.mp4" />
<video src="mp4:test/waf_2386_preview_360p.mp4" system-bitrate="600000" />
<video src="mp4:test/waf_2386_preview_720p.mp4" system-bitrate="1200000" />
I have the <meta> base pointing to the proper location and have made sure to include the mp4: in the stream names to allow it to properly play H.264 MP4 content.
Finally, I point the source property of the FLVPlayback instance to the http location of the SMIL file:
video.source = http://x.com/test/waf_2385_preview.smil;
The trouble I am having is related to the NetConnection manager(s) that FLVPlayback uses. With the above code, if I set the following before the source:
VideoPlayer.iNCManagerClass = fl.video.NCManagerNative;
the first video in the playlist (the 180p file) begins to play fine but it's ALWAYS the 180p file that it plays. It's as if the FLVPlayback component never performs a bandwidth calculation to determine which stream it should connect to. Setting the video.bitrate property to a static value such as 800000 to have it automatically connect to the 360p file doesn't seem to do anything either... it will still load the first file in the list, which happens to be the 180p file.
However, to take advantage of dynamic streaming, all the articles I have said you need to use the following code:
VideoPlayer.iNCManagerClass = fl.video.NCManagerDynamicStream;
When I use this code, FLVPlayback seems to pull the SMIL file off the server but then does absolutely nothing with it... it doesn't buffer, doesn't fire any video events, nada.
Any help or advice in getting this to work would be greatly appreciated.
Digital Media Developer
For the NCManagerNative method, reverse the order of the bitrates in the SMIL file. Highest to lowest.
For the DynamicStream NCManager (which is by default in FLVPLayback 2.5) try defaulting the lowest system-bitrate to 0.
I too have noticed some unpredictable playback issues, even with FLV Playback 188.8.131.52. When I was testing with the sample dynamic streaming content that comes with FMS 3.5, I found two possible scenarios.
1) Download the video stream as normal over LAN. Quickly, the player will adjust to playback the highest quality. During playback, I enable NetLimiter to significantly reduce my bandwidth so that I would fall into the lower streaming bracket. Eventually the video buffer depletes and the player goes into buffer mode; however the player never reduces video quality. It eventually becomes a stop-and-go experience for the remainder of the video.
2) On the same stream, I stopped the video and reset the source. When the video started (NetLimiter is enabled here), I noticed the player continued to run the highest quality and remained there. It spent a couple seconds buffering and once again went into a stop-and-go experience.
Maybe NetLimiter is to blame here, I don't really trust it and I would have preferred to limit the bandwidth from FMS (the server options don't seem to work). If the OP does get this to work, I would like to know so that I can feel better about my testing environment.
Thanks for the extremely timely response! I hadn't even finished driving home from work when I received the email on my phone.
In short, I've discovered that the reason I could not get the Dynamic Streaming to function with FLVPlayback and our Limelight account is the fact that the server we are on has apparently not yet been upgraded to FMS 3.5. I installed the Developer Edition of FMS 3.5 on a spare machine here at work and now Dynamic Streaming works fine.
Also, to augment what another user has posted, I too am noticing some inconsistencies when using NetLimiter to test stream switching. Sometimes it works, sometimes it just sits there and buffers repeatedly... I am guessing this is probably an effect of how NetLimiter throttles the bandwidth.
Thanks again for your help and suggestions!
In regards to the last post about the continous buffering issue-
When I used Telestream's Episode application I would get the same problem. Episode's provided templates seem to add something to the video compression that FMS 3.5 does not like. Though, I had great results with Square1's MPEG Streamclip and Apple's Compressor application. Have not tried Adobe's Encoder application. Here's an example of how I have been using dynamic streaming.
Sorry, I have one more quick question... how does the FLVPlayback component handle nonexistent/invalid stream names in a SMIL file? Will it successively try each one until it finds one that works? Does it "skip over" these invalid files when it dynamically switches streams?
@seanhsmith - NetLimiter is sufficient but not really the best to be testing the dynamic streaming with. In short, NetLimiter works by sending data, then withholding data for a few seconds alternating. It isn't necessarily characteristic of real world behavior. We've mostly switched to using the Shunra desktop client now since it's more reliable.
Regarding the invalid stream names. It won't check the validity of the stream names for unsupported characters, etc.... However, the failover behavior in the DynamicStream class (which is what FLVPlayback uses) falls back to the previous stream ID it was playing before it attempted to switch. If the initial stream play doesn't work, it will likely fail. I have a note to myself to do some house keeping in this area. I just don't know when I'll be getting around to it.
@ewhutson - I'm not familiar of any issues using Telestream content, but that is helpful to know. I will let our Quality Engineer's know about this. If you don't have an issue sharing the broken content, I would like to get that to our QE's so that they can add it to our testing metrics.
Since we cannot set a "scalable" value to the width and height properties of FLVPlayback (i.e., 100% of the container its container), is there a way to use the fullScreenTakeover method but also allow control elements to be layered on top of it? Or, is there another, reliable way to detect the current monitor (not primary monitor) through Flash that you know of? Hulu's media player does not appear to be affected by this issue in any browser and I haven't been able to find a solution for it either.
In case I wasn't making any sense above, an easy way to test and see what I'm talking about is create a simple app with two buttons. When you click each button, set the source property of the FLVPlayback instance to a different SMIL file -- the first one you do should load fine but trying to switch to the other one results in nothing happening if you have no event listeners or the VideoError.NO_CONNECTION event error being thrown during the VideoEvent.STATE_CHANGE event.
I should note that this does NOT seem to happen if you are simply pointing to a single video file through the source property -- it seems to be only switching sources between SMIL files that present a problem.
Thanks for the suggestion. I tried this earlier today while I was at work and it didn't seem to solve the problem I'm having. As I said before, we are using SMIL files for all of our video content since we offer multiple bitrates for the same content and I wanted to take advantage of dynamic streaming now that it's available. The first time I set the source property to a SMIL file when the player loads, everything works fine. The problem is when I try to load another video into the player... every other SMIL file other than the inital one that loads results in a VideoEvent.STATE_CHANGE event firing with a VideoEvent.CONNECTION_ERROR type and the video(s) never play. As soon as I load the initial SMIL file again, it works fine. What I don't understand is that everytime I go to load another video, I stop/close the current video, unregister all of the FLVPlayback instance's event listeners, and then literally re-create the instance again by using = new FLVPlayback() so it should be creating a new instance each time, yes?
Are all your SMIL playlists multibitrate or are you switching between multibitrate and common progressive / RTMP protocols? I didn't notice any problem switching between SMIL playlists in our player. It was only when switching between dynamic and regular streams that the FLVPlayback threw an exception. It didn't matter if they were SMIL or not. Also, if memory serves, the net stream class is a static member in the video player. Since that was the class I had issues with, if you didn't patch it then your new FLVPlayback instance is likely still using a corrupted state and hence why you're still getting the error.
I would suggest you load the FLVPlayback source code into your project. Generate the exception again and trace the issue back into their source code to find out what's causing it.
Pretty much all of our SMIL files are multi-bitrate... we've done two encodes for all of our content since before I've been working here. There are a few pieces that could possibly only have a single video element in the