Video and the web are long time friends already, you see lots of websites with some sot of player for video content, you also see media companies and television channels serving video over the wire to the end users.
Video can be downloaded (progressive download) to the client like YouTube or can be streamed to him.
I won’t discuss the pro’s & con’s of streaming and progressive, we will only be discussing streaming in this post.
So, What is the post worthy problem we have when streaming video to the client?
Continue reading and find out.
When streaming video, you usually encode your video in a certain bitrate, this bitrate will work well in certain computers and won’t work well in others.
Why is that?
That’s because each of your users has a different connection thus being capable to receive a limited amount of bytes streamed to him.
So, you always have to find the “sweet spot” where you deliver a video that looks good and also light enough to fit a wider range of network connection speeds.
That is of course a problem becuase sometimes you want to stream hiQuality video and audio (HD) and you can’t because some of your users won’t be able to watch it smoothly.
Well, this is a problem we will solve here in this post.
Flash media server introduced a new way of streaming video to the client, it is called dynamic streaming and it is very dynamic (name implies just that).
That way, you can create several encodes to the same source movie and supply a movie best fit to the user cosuming it.
Another obvious advantage of this approach is the way it skips on top of the movie, when you skip to a further point in the movie, you are actually being supplied a different movie from the lowest quality to the highest.
So, how is it done, first, let’s create a flash file (I’m using flash CS4).
Now, we will create (by dragging and dropping from the components panel) an FLVPlayback control.
We will give it the same dimensions as the movie itself so it will fill the entire surface.
Now, we will give the player an instance name of “flvPlayer”
so, we have a movie, we have an FLVPlayback control, we called it “flvPlayer”.
We will create another layer, called “action script” and we will create this code inside.
import fl.video.*; VideoPlayer.iNCManagerClass = NCManagerDynamicStream; flvPlayer.source = "dynamicStream.smil";
OK, so as we can see we created a pointer to a file called “dynamicStream.smil”, this is a special file (XML format).
This file details the following
- FMS Url
- files you have encoded and a network speed in correlation
The file looks like this:
<smil>
<head>
<meta base="rtmp://your_fms_location/vod/" />
</head>
<body>
<switch>
<video src="mp4:erets7_03_vod1_300.mp4" system-bitrate="300000"/>
<video src="mp4:erets7_03_vod1_500.mp4" system-bitrate="500000"/>
<video src="mp4:erets7_03_vod1_800.mp4" system-bitrate="800000"/>
</switch>
</body>
</smil>
Now, when we put this file on our web-server, the user will get the file it can receive and play, not slower, not faster, just the perfect file for him.
NO buffering, NO waiting, NO frustration, smooth, cool and fast user experience.
Good luck.
You can download the complete solution from here:
Source - Dynamic streaming (flash media server) (112)

Hi
i am playing advertisement video with another video(movies).i am streaming video(movies)
using FMS and advertisement video using HTTP protocol . i pause running video and play
advertisement video at specified position .but i am facing one problem . problem is here.
whenever advertisement video play then running video is paused . playhead for running video
is moved more than specified position but advertisement video play fine.
For Example:- when i am playing advertisement video at 30 seconds .then running video pause at
30 seconds and playhead should be at 30 seconds until advertisement video is completed but
playhead is moved more 30 seconds.
so please tell me about “why is this happening ” and ” what am i doing wrong”
Thanks in advance
@Dileep Kumar:
I don’t quite understand what your problem is.
I will need to see some code or some sort of example to see what the problem is.
Thanks,
i am sending code .so please check it.
public class ClassVideoPlayer{
//VARS
private var targetRoot : Object
private var root : MovieClip
public var videoSprite : Sprite
public var video_width : Number
public var video_height : Number
private var recommendWidth : Number
private var recommendHeight : Number
private var video_duration : Number
public var vscale : String
private var streamPath : String
public var serverType : String // -http -rtmp
private var liveStreamPath : String
private var liveStreamServer : String
private var myVideo : Video
private var nc : NetConnection
private var ns : NetStream
private var nsCallBack : Object
private var onvideoload : Function
private var videopreload : Function
public var onvideoend : Function
private var videoPreloadTimer : Timer
private var bufferTimer : Timer;
public var vstatus : String
public var vloop : Boolean
private var onbufferFull : Function
private var onbufferEmpty : Function
public var LimelightServer : Boolean
public var ADflag : Number=0;
public var rflag : Number=0
var adflag : Number=0;
// CONSTANTS
private const CONST_video_width = 320
private const CONST_video_height = 240
public const VIDEO_PLAYING = ‘playing’
public const VIDEO_STOP = ‘stop’
public const VIDEO_PAUSE = ‘pause’
function ClassVideoPlayer(settings) {
root = ClassUtils.root
setDefaultValues()
targetRoot = settings.target
vscale = settings.vscale
recommendWidth = settings.recommendWidth
recommendHeight = settings.recommendHeight
onvideoload = settings.onvideoload
videopreload = settings.videopreload
onvideoend = settings.onvideoend
vloop = settings.vloop
nsCallBack = new Object()
if(typeof(settings.onbufferFull)== ‘function’){
onbufferFull = settings.onbufferFull
}
if(typeof(settings.onbufferEmpty)== ‘function’){
onbufferEmpty = settings.onbufferEmpty
}
videoPreloadTimer = new Timer(50)
//bufferTimer = new Timer(50);
videoPreloadTimer.addEventListener(TimerEvent.TIMER, getvideoload)
//bufferTimer.addEventListener(TimerEvent.TIMER,checkbufferStatus);
var ncclient : Object = new Object()
ncclient.onBWDone = onBWDone
ncclient.onFCSubscribe = onFCSubscribe
videoSprite = new Sprite()
videoSprite.name = settings.targetName
targetRoot.addChild(videoSprite)
myVideo = new Video()
myVideo.smoothing = true
videoSprite.addChild(myVideo)
nc = new NetConnection()
nc.client = ncclient
nc.connect(null)
nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
nc.addEventListener(NetStatusEvent.NET_STATUS, netConnectionHandler);
initNetStream()
}
// AsyncErrorEvent
function asyncErrorHandler(event:AsyncErrorEvent):void {
//trace(event.text);
}
//Handle the Call
function onBWDone(…args):void{
//trace ( “onBWDone! : ” + args );
}
// Limelight Server
public function onFCSubscribe(info:Object):void {
initNetStream()
ns.play(info.description)
}
// INIT NET STREAM
function initNetStream() {
nsCallBack.onMetaData = onMetaDataHandler
ns = null
ns = new NetStream(nc)
ns.client = nsCallBack
//ns.bufferTime = 10
ns.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler)
myVideo.attachNetStream(ns)
}
// NET STATUS EVENT
function netConnectionHandler(event:NetStatusEvent):void {
//trace(event.info.code)
if (event.info.code == ‘NetConnection.Connect.Rejected’) {
root.classError.show(‘Error!\n’+'Server Rejected Connection’)
}
if (event.info.code == “NetConnection.Connect.Success” && serverType == ‘rtmp’) {
if (LimelightServer) {
nc.call(‘FCSubscribe’, null, liveStreamPath);
}else {
trace(‘initNetStream’)
initNetStream()
this.liveplay()
}
}
}
// SET DEFAULT VALUES
private function setDefaultValues():void{
video_width = CONST_video_width
video_height = CONST_video_height
vscale = ‘original’
vloop = false
}
// META DATA INFO
private function onMetaDataHandler(metaInfoObj:Object):void{
if(Number(metaInfoObj.width)>0) video_width = metaInfoObj.width
if(Number(metaInfoObj.height)>0) video_height = metaInfoObj.height
if(Number(metaInfoObj.duration)>0) video_duration = metaInfoObj.duration
setVideoSize()
for(var key:String in metaInfoObj){
trace(key+’= ‘+metaInfoObj[key])
}
}
// NetStatusEvent.NET_STATUS
private function netStatusHandler(e:NetStatusEvent):void{
if(e.info.code)
if(e.info.code == ‘NetStream.Play.Start’){
trace(“Start”)
setVideoSize()
}
if(e.info.code == ‘NetStream.Buffer.Full’){
if(this.onbufferFull!=null){
this.onbufferFull()
}
}
if( e.info.code == ‘NetStream.Seek.InvalidTime’){
trace(“File is not well structured”)
}
if(e.info.code == ‘NetStream.Buffer.Empty’ || e.info.code == ‘NetStream.Seek.InvalidTime’ || e.info.code == ‘NetStream.Play.Start’){
if(this.onbufferEmpty!=null){
this.onbufferEmpty()
}
}
if(e.info.code == ‘NetStream.Play.Stop’){
vstatus = VIDEO_STOP
trace(adflag)
if(adflag==1){
root.classNavigation.ShowRelatedVideo();
}else{
if(this.vloop){
this.play()
}else{
if(this.onvideoend!=null){
this.onvideoend()
}
}
}
}
}
// SET VIDEO SIZE
private function setVideoSize():void{
manualVideoSize(recommendWidth,recommendHeight,vscale)
}
// SET MANUAL VIDEO SIZE
public function manualVideoSize(vwidth,vheight,vscale,noevent:Boolean=false):void{
var coef:Number
if(vscale == ‘fitw’){
myVideo.width = vwidth
coef = video_height/video_width
myVideo.height = vwidth * coef
}
if(vscale == ‘fith’){
myVideo.height = root.stage.stageHeight
//coef = video_width/video_height
myVideo.width = root.stage.stageWidth
}
if(vscale==’scale’){
myVideo.width = vwidth
myVideo.height = vheight
}
if(vscale==’original’){
myVideo.width = video_width
myVideo.height = video_height
}
if(onvideoload!=null && !noevent){
onvideoload()
}
}
// LIVE PLAY RTMP
private function liveplay(){
trace(liveStreamPath)
ns.play(String(liveStreamPath))
}
// PLAYER PLAY
public function play(streamPath = undefined, duration = undefined):void {
this.stop()
if(duration!=undefined){
video_duration = duration
}
if(streamPath == undefined){
streamPath = this.streamPath
}else{
this.streamPath = streamPath
}
if(root.classMediaAd==undefined){
adflag=1;
}else{
if(!(root.classMediaAd.adModeON)){
adflag=1
}else{
adflag=0
}
}
if(streamPath.indexOf(‘rtmp://’)!=-1){
serverType = ‘rtmp’
liveStreamPath = streamPath
liveStreamServer = streamPath
liveStreamServer = liveStreamServer.substr(0,liveStreamServer.lastIndexOf(‘/’)+1)
liveStreamPath = liveStreamPath.substr(liveStreamServer.lastIndexOf(‘/’)+1, (liveStreamPath.length – liveStreamServer.lastIndexOf(‘/’)))
nc.connect(liveStreamServer)
///ns.play(streamPath)
}else{
serverType = ‘http’
nc.connect(null)
initNetStream()
trace(streamPath)
ns.play(String(streamPath))
}
videoPreloadTimer.start()
vstatus = VIDEO_PLAYING
}
// PLAYER STOP
public function stop():void{
ns.close()
vstatus = VIDEO_STOP
}
// PLAYER PAUSE
public function pause():void {
if (vstatus == VIDEO_PLAYING) {
ns.pause()
vstatus = VIDEO_PAUSE
}
}
function AddVideo(ad:Object):void{
var VidSprite:Sprite=new Sprite();
myVideo.width=301;
myVideo.height=214;
myVideo.x=-150.5;
myVideo.y=-107;
VidSprite.addChild(myVideo);
ad.addChild(VidSprite);
}
function ReturnVideo():void{
//SEFlag=0;
videoSprite.addChild(myVideo);
targetRoot.addChild(videoSprite);
myVideo.x=0;
myVideo.y=0;
setVideoSize();
}
// PLAYER RESUME PLAY
public function resume():void{
ns.resume()
vstatus = VIDEO_PLAYING
}
// PLAYER togglePause
public function togglePause():void{
ns.togglePause()
vstatus = VIDEO_PAUSE
}
// GET CURRENT TIME
public function get time():Number{
//trace(ns.time)
return ns.time
}
// GET VIDEO DURATION
public function get duration():Number{
return video_duration
}
// SEEK VIDEO
public function seek(percent):void{
var newseek = percent/100*video_duration
ns.seek(newseek)
}
// PRELOAD VIDEO
private function getvideoload(e:TimerEvent):void{
if(this.getBytesTotal == this.getBytesLoaded){
videoPreloadTimer.stop()
if(videopreload!=null){
videopreload(true)
}
}else{
if(videopreload!=null){
videopreload(false)
}
}
}
// GET VIDEO TOTAL BYTES
public function get getBytesTotal():Number{
return ns.bytesTotal
}
// GET VIDEO LOADED BYTES
public function get getBytesLoaded():Number{
return ns.bytesLoaded
}
// SET VOLUME
public function set volume(value):void{
ns.soundTransform = new SoundTransform(value)
}
// GET VOLUEM
public function get volume():Number{
return ns.soundTransform.volume
}
// SET VIDEO FILE
public function set file(value):void{
streamPath = value
}
// SET CUSTOM VIDEO SIZE
public function setCustomVideoSize(vwidth,vheight):void{
recommendWidth = vwidth
recommendHeight = vheight
}
// SET BUFFER TIME
public function set bufferTime(value):void{
ns.bufferTime = value
}
// GET BUFFERING VALUE
public function getBuffering():Number{
var value = 0
value = Math.round(ns.bufferLength / ns.bufferTime*100)
return value
}
// SET VIDEO SMOOTHING
public function set smoothing(value:Boolean):void{
myVideo.smoothing = value
}
// GET PERCENT OF PLATING STREAM
public function get percent():Number{
return (time/duration)
}
// CLEAR VIDEO STAGE
public function clear(){
myVideo.clear()
}
}
}
i am creating two object of this class that i am sending code for u . first object for playing movie and another is for playing advertise video.if i play movies and advertise video by using web server(http protocol). then it works fine. but just i play movie by using rtmp protocol .then i face this type of problem
i am explaining what i am doing
Actually i want to play advertise video at particular periods when movie is running.so i have created two class . one for playing and handling video and another is for checking time periods to play advertise video.
it is working fine by using http protocol. both movie and advertise video are playing properly.but it is not working with rtmp protocol .
problem only is here. movie start properly. as playhead reaches to particular period. playhead immediately goes ahead. after moving, movies is paused and start playing advertise video.
i have reviewed code more time . but i am unable to understand this problem.
so please guide me what to do
Thanks in advance
Great, I never knew this, thanks.
Hi
i am playing advertisement video with another video(movies).i am streaming video(movies)
using FMS and advertisement video using HTTP protocol . i pause running video and play
advertisement video at specified position .but i am facing one problem . problem is here.
whenever advertisement video play then running video is paused . playhead for running video
is moved more than specified position but advertisement video play fine.
For Example:- when i am playing advertisement video at 30 seconds .then running video pause at
30 seconds and playhead should be at 30 seconds until advertisement video is completed but
playhead is moved more 30 seconds.
so please tell me about “why is this happening ” and ” what am i doing wrong”
Thanks in advance
It’s posts like this that keep me coming back and checking this site regularly, thanks for the info!
Keep posting stuff like this i really like it
Hello,
do you know if FMS only falls back to lower quality when an insufficient connection is in place or it will get back to the top bitrate if connection improves?
@Nikola:
The answer to your question is yes, Flash and FMS will continue checking for your connection quality and move you back and forth between streams.