Requirements

Understanding live DVR – Part 1: Implementing a live DVR player

 

 


Requirements

Prerequisite knowledge

General familiarity with Flash streaming media and programming ActionScript 3.0 in Adobe Flash or Adobe Flex.

User level

Intermediate

 

 

Sample files

  live_dvr_pt1.zip (5318 KB)

 

 

 

This article provides a high-level overview of the new live DVR (digital video recorder) functionality of Adobe Flash Media Server 3.5. It explains the basics and opportunities of live DVR on the web and will inspire you with what is possible by means of a simple example covering the suite of Adobe tools available for streaming and consuming live DVR-enabled content.

DVR functionality was introduced with Flash Media Interactive Server 3.5:

  • To publishlive DVR-enabled content, one of the best solutions is Flash Media Live Encoder 3.0, which now has DVR-enabling capabilities. However, in this article, I will focus on developing a publishing solution from scratch using Adobe Flash Player as the video capture solution.
  • To consumelive DVR-enabled content, no specific Flash Player or Adobe AIR version is required. Therefore, any Flash Player version 6 or later should work just fine, depending on the video codec being used.

Note: DVR functionality is not available with Flash Media Streaming Server because of the server-side caching/recording requirements.

Live DVR is the process of recording or "caching" a live video stream on the server and then enabling viewer access to the live or recorded stream content as it streams. A unique opportunity for this approach is making the video-on-demand (VOD) content available quickly following the live event without the time-consuming requirement of sending, encoding, and uploading it. The recorded content can simply be made available as VOD content.

After reading Part 1, you should have a solid grasp of how to enable a live DVR stream and how you can begin offering new engaging experiences to your customers. Part 2 shows you how to implement the new DVRCast server-side sample application from Adobe, as well as stream and record content with Flash Media Live Encoder 3 and play back the live DVR content with the FLVPlayback 2.5 component.

 

DVR importance

 

The first thing to understand is the importance of the DVR function. Before the ability to efficiently record video at home, video consumers were limited to watching television content only when it was being broadcasted live at the discretion of the broadcaster. Many times you could see only your favorite shows, or important moments in live events. It became clear that consumers wanted to watch content on their own time, instead of changing their schedules to adhere to that of the broadcaster. This was a consumer requirement, not a broadcaster requirement—to free users from the time constraints of live-only content.

The first solution on the market was the videocassette recorder (VCR). These were limited to recording television broadcasts in a linear fashion. This approach solved a problem, but consumers had trouble even setting the VCR clock, not to mention navigating an unfriendly menu system to program the recording device properly. Thankfully, the solution has evolved over the years to provide, and now even help influence, the user experience when it comes to video content delivered to the homes of millions of people.

Today, many people leverage the power of shelf-top DVRs and are able to watch content from their televisions when they want to instead of only having a small window of time when it is actually viewable and "live" on the air. Broadcasters have also adopted new business models that revolve around in-home DVR or PVR technology—demonstrating the democratization of broadcast media.

With the evolution of broadcast television and the ability to watch time-shifted content with pause and seek functionality, why wouldn't that same standard apply to the web?

With current web-based streaming technologies, including previous versions of Flash Media Server, there is a hard line between the experience of live versus recorded content. Recorded content can be played back at any time, and has all the standard controls one would assume: pause, seek, and so on. Live streaming, unfortunately, has been like the pre-VCR era of broadcast television: a time-fixed event that users can join and see the content as it is being streamed, but cannot view any of the previously recorded content for that event while the live recording is still in progress. This issue and the separation of desired functionality is exasperating; for instance, if users join the live event after it starts, they are unable to see any of the preceding content while the session is still live. Being a few minutes late often negates much of the relevancy of an online event as a whole.

 

DVR benefits

 

Adobe has brought web-based video up to par with broadcast television and opened up significant new business opportunities that only the web can deliver. The live DVR functionality has many new use cases for a variety of users and markets. The reality is that, for any live event, there is no reason not to offer this functionality. It expands the functionality of an existing event and helps free your users from stringent time constraints. It's also what they want.

Events such as conferences, concerts, internal communication, sports, and news—which may be long or short in duration, or multiple sessions available simultaneously—can have high value in the live DVR functionality, especially if the content viewing is monetized, because many users can benefit from it. It also offers a distinguishing feature for how your content is made available. The ability for users to surf multiple sessions simultaneously and view previous content can have a perceived high value. Once again, it brings the common user experience of watching and controlling television into the realm of streaming video.

 

DVR use cases

 

One common use case for live DVR functionality is if a user needs to pause the live stream to handle a short task such as a phone call or other distraction. Without live DVR, the user would simply have to miss a portion of the live event, and at best review the missed portion later, when and if it is made available.

Another common use case is when a user might want to rewind briefly in the session and replay a small portion for a closer look—common used in sports for instant replays. With live DVR, users can control their own video feeds and jump back for an instant replay of that great catch, score, or foul. With many of the major league sports turning to Flash Media Server video streaming, this functionality will surely have an increased value. Also attractive is the ability to provide multiple camera angles. Live DVR can be applied to any existing live scenario including multiple-camera and multiple bit-rate dynamic streaming.

 

Overview of workflow changes

 

One of the greatest advantages with live DVR functionality in Flash with Flash Media Interactive Server 3.5 is that there is nothing special you have to do on the server or the client. All this great functionality in its simplest form is available right out of the box with the same processes already being used to stream and record, and then have a client access the content. The very root of the live DVR functionality of Flash Media Server is its ability to stream video as it is being recorded. This was the biggest problem Adobe solved, plus the ability to scale the delivery and functionality through content delivery networks (CDNs).

 

Understanding the NetStream.Play options

The client controls the DVR playback, not the server. Control is achieved through the NetStream ActionScript class. This class is responsible for managing the playback; specifically, the NetStream.play or NetStream.play2 commands.

The key point in all of this is that, instead of playing the live stream, you actually play the recorded (live cache) stream as if it were a VOD stream. This is done from the client-side NetStream.play() or play2() methods and the start time parameter. For the older play() method, the start time parameter is the second parameter directly following the stream id. The new play2() method (Flash Player 10 and later) uses the NetStreamPlayOptions class as its parameter and a start property within the class. Have a look at the NetStream.play(), and the NetStream.play2() method API references.

By default the of NetStream.play() start parameter value is –2, instructing Flash Player to play a live stream first and, if that does not exist, to play a recorded stream if it exists with that ID. If neither stream exists it will create a live stream and wait. To play a recorded stream, the parameter is set to a value > 0 unless you want to limit the amount of time a specific user can seek back in time. In that case, a value of 0 would indicate to start playing back the recorded file from the beginning. If a value > 1 is specified, it will start the playback from there, in seconds, and will not allow the client to seek to a point previous in the video's timeline.

Here are some examples. The following looks for a live stream first, then a recorded stream. If neither of those is available, it creates a live stream and waits for content:

 

NetStream.play(streamID, -2);

 

The following looks for a live stream only and plays it if it exists:

 

NetStream.play(streamID, -1);

 

The following plays a recorded stream from the beginning, and allows users to seek back to any time in the stream:

 

NetStream.play(streamID, 0);

 

The following plays a recorded stream from 10 seconds in, but prevents the user from seeking to the first 10 seconds of the stream:

 

NetStream.play(streamID, 10);

 

Setting the "start" parameter to a value > 1 can be valuable for live DVR if there is a need to trim the beginning of the recording made available to users, perhaps during startup or preparation. From there you can seek, pause, play, and catch up just as you normally would. It's important to make sure you want live DVR functionality to allow the client applications to play the recorded stream, not the actual live stream.

One commonly implemented feature is the ability to seek to the latest point in the stream that would most closely represent the live content. For simplicity's sake, this will be referred to as the live point. Figure 1 illustrates the workflow to consider.

 

 

This workflow would often be called immediately upon playing, so that users start at the live point and then are given the option to seek back in the timeline of the content if they choose. So you would have the users first play at the beginning of the content intended for DVR access (40 seconds from the start in Figure 1) and then seek their view of the stream to the live point. It is important to note that you should not try to play the live recording stream immediately from the live point. Calling the initial play command with the current live point as its start time will limit the backwards-seeking window to that initialized point.

To ensure that viewers do not see any content on the DVR-cached stream that occurs at the beginning of the cache (also known as the dirty head of the stream), make sure tyou don't start users at the very beginning of the stream, or else they will be able to seek back to it. The same applies at the end of the stream. Close viewers' streams before the end of the cache to allow more content at the end of the stream to be made unavailable to viewers.

 

Best practices

A best practice is to start playing the stream at the DVR-accessible content start time. Once the client application's NetStream instance broadcasts a NetStatusEvent with the event.info.code value of "NetStream.Play.Start," invoke the seek() method of the NetStream instance and seek to the live point in the content, which you can determine by the metadata or initially by seeking to a very high value, such as 1000000.

For best management and performance, we recommend that you keep track of the live point either with a server messaging solution or locally for each client. A solution for managing this locally for a client application will be explored in the upcoming walkthrough. A nice tip to know is that, if you ever try and seek past the available duration in a live DVR stream, it will end up seeking to the live point in the end, but does not perform as fast as knowing the appropriate seek time, as it will flush the buffer and reinvoke the stream. However, if the live event is over and a user tries to seek past the end, it will restart the stream from the beginning, as is standard with the media server.

Another important note regarding live DVR and playing content at a determined live point is that Flash Media Server has to process the live video and make it accessible to the recorded streaming mechanisms on the fly as the stream comes in. What this means for the user is that, if they are viewing a live DVR stream, they will always experience a little delay in the content compared to the true live stream that is still available. This is not a fixed delay and can vary depending on many factors, such as hardware, cache size, video quality, and encoding parameters.

 

 

Walkthrough 1: Enabling DVR on a live stream

 

In this walkthrough you will:

  • Implement a DVR-enabled publisher for broadcasting video (see Figure 2)
  • Publish video from the publisher component and a web cam

 

 
  1. Create a new, empty, dvr directory in the {Flash Media Server Install}/applications/ directory.
  2. Open the file DVR-FlashConsumerPublisher.fla in the {start files}/hands-on/DVR-Publishing/start/ directory.
  3. Set the Document class property to the following (see Figure 3):

 

com.realeyes.dvr.FlashConsumerPublisher

 

 
  1. Open the FlashConsumerPublisher class in the {start files}/hands-on/DVR-Publishing/start /com/realeyes/dvr/ directory. The FlashConsumerPublisher class manages the connection and passes the NetConnection and stream name to the VideoConsumer and VideoPublisher classes (you will work with these later), so the connection is shared between the two.
  2. In the FlashConsumerPublisher class, locate the following comment:

 

// Declare connection path and video ID
 
  1. Declare a public String property named connURI and set it equal to the rtmp:// path to the dvr application on your server:

 

// Declare connection path and video ID public var connURI:String = "rtmp://{your server}/dvr";
 
  1. Declare the public String property vidID and set it equal to "myDVR" :

 

// Declare connection path and video ID public var connURI:String = "rtmp://{your server}/dvr"; public var vidID:String = "myDVR";
 
  1. Open the VideoPublisher.as file in the {start files}/DVR-FlashConsumerPublisher/com/realeyes/dvr/ directory and locate the following comment that begins:

 

//Attach cam
 
  1. Under this comment, call the attachCamera() method on the _ns NetStream object and pass it the cam variable:

 

//Attach cam, audio, and publish, also display in video for monitoring _ns.attachCamera( cam );
 
  1. Attach the sound by calling the attachAudio() method on the _ns NetStream object and pass it the result of the call to Microphone.getMicrophone() :

 

//Attach cam, audio, and publish, also display in video for monitoring _ns.attachCamera( cam ); _ns.attachAudio( Microphone.getMicrophone() );
 
  1. Call the publish() method on the _ns method and pass it the vidID property as the first parameter and the String "record" as the second parameter:

 

//Attach cam, audio, and publish, also display in video for monitoring _ns.attachCamera( cam ); _ns.attachAudio( Microphone.getMicrophone() ); _ns.publish( vidID, "record");
 
  1. To complete the _onPublish() method, call the attachCamera() method on the publisherVideo Video object and pass it the cam variable as its only parameter:

 

//Attach cam, audio, and publish, also display in video for monitoring _ns.attachCamera( cam ); _ns.attachAudio( Microphone.getMicrophone() ); _ns.publish( vidID, "record"); publisherVideo.attachCamera( cam );
 
  1. Return to the DVR-FlashConsumerPublisher.fla file and test the SWF in Flash (Control > Test Movie). If you have a camera attached, you should be able to click the Publish button and see the video you are broadcasting.

Now you have created the functionality to publish your video to the server and record it. Next, you need to create the functionality for consuming video that has been DVR-enabled. Once you are done with the next walkthrough, you will be able to play back the DVR-enabled video.

 

Walkthrough 2: Consuming a DVR-enabled live stream

 

In this walkthrough you will:

  • Implement a video player for viewing DVR-enabled video
  • Enable the ability for replay and catch-up back to the live point (see Figure 4)

 

 

Note: This walkthrough is a continuation from Walkthrough 1: Enabling DVR on a live stream. You can either use the same files used in that walkthrough or open a fresh starting set from the {start files}/hands-on/DVR-Consuming/start/ directory.

  1. Open the VideoConsumer.as file in the /com/realeyes/dvr/ directory and locate the _onPlay() method. You can use the files from the first walkthrough, or open the start files in the /DVR-Consuming/start/ directory.
  2. Inside the method, add a call to the _initConsumerDisplay() method.
  3. Locate the _initConsumerDisplay() method. Inside that method, find the comment that begins:

 

//Play and specify...

 

Under this comment, call the play() method on the _ns NetStream object, passing it the property vidID as the first parameter, zero (0) for the second parameter, and negative one (-1) as the third and final parameter:

 

// Play and specify 0 for start, -1 for dur _ns.play( vidID, 0, -1 );
 
  1. Call the attachNetStream() method on the consumerVideo Video object and pass it the _ns NetStream object:

 

// Play and specify 0 for start, -1 for dur
 
  1. Make sure the completed method looks like the following:

 

private function _initConsumerDisplay():void { _ns = new NetStream(nc); _ns.client = new ConsumerClient( this ); _ns.addEventListener( NetStatusEvent.NET_STATUS, _onNetStatus ); _ns.addEventListener( AsyncErrorEvent.ASYNC_ERROR, _onAsyncError ); //Start tracking the time timer.addEventListener( TimerEvent.TIMER, _onTimer, false, 0, true ); _timer.start(); // Play and specify 0 for start, -1 for dur _ns.play( vidID, 0, -1 ); consumerVideo.attachNetStream( _ns ); }
 
  1. Locate the _onReplay() method. Inside this method, add a call to the replay() method and pass it the value property of the replayTime_ns object:

 

replay( replayTime_ns.value );

 

The completed _onReplay() method should look like the following:

 

private function _onReplay( p_evt:MouseEvent ):void { replay( replayTime_ns.value ); }
  1. Locate the replay() method. Under the comment in the method, call the seek() method on the _ns NetStream object and pass it the result of _ns.time minus the p_time argument. The completed method should look like the following:
public function replay( p_time:Number ):void { //Set seek time to current position minus the jump back time _ns.seek( _ns.time - p_time ); }
  1. Locate the onMetaData() method in the ConsumerClient internal class. Under the comment that begins:
//Set the cur duration...

set the recordedDuration property of the _owner object equal to the duration property of the p_info object:

//Set the cur duration from metadata when received _owner.recordedDuration = p_info.duration;
  1. Locate the implicit getter/setter methods for recordedDuration. They have been commented out.
  2. Uncomment the getter and setter by removing the /* before the getter and */ after the setter's last curly brace.
  3. Under the comment that begins:
//Create a local variable...

create a local Number variable called timeSinceLastDuration and set it equal to the result of a call to the getTimer() method minus _lastRecordedTime:

//Create the local var for timeSinceLastDuration var timeSinceLastDuration:Number = getTimer() - _lastRecordedTime;
  1. To finish off the recordedDuration getter method, return the result of _lastRecordedDuration plus the value of timeSinceLastDuration divided by one thousand (1000):
return _lastRecordedDuration + ( timeSinceLastDuration / 1000;

The completed getter method should look like the following:

public function get recordedDuration():Number { //Create the local var for timeSinceLastDuration var timeSinceLastDuration:Number = getTimer() - _lastRecordedTime; //Return the estimated duration adjusting for miliseconds return _lastRecordedDuration + ( timeSinceLastDuration / 1000 ) ; }
  1. In the implicit setter method for recordedDuration, under the comment that begins:
// Track the value...

set the value of _lastRecordedDuration equal to the argument value:

// Track the value and store a initial time for comparision later _lastRecordedDuration = p_value;
  1. Set the value of _lastRecordedTime equal to the result of a call to the getTimer() method:
// Track the value and store a initial time for comparision later _lastRecordedDuration = p_value; _lastRecordedTime = getTimer();

The completed setter method for recordedDuration should look similar to the following:

public function set recordedDuration( p_value:Number ):void { // Track the value and store a initial time for comparision later _lastRecordedDuration = p_value; _lastRecordedTime = getTimer(); }
  1. Locate the _onRestart() method. In this method, call the NetStream's seek method to send the stream back to 0 seconds:
private function _onRestart( p_evt:MouseEvent ):void { _ns.seek( 0 ); }
  1. Locate the _onCatchup() method. Inside the method add a call to the catchup() method.
  2. Locate the catchup() method. Under the explanation that starts:
/* Optimized ...

call the seek() method on the _ns NetStream object and pass it the recordedDuration property:

public function catchup():void { //Simple way //_ns.seek( 100000 ); /* Optimized way - though with this example assumes the video recording hasn't stopped or paused during the whole playback or video will restart if seeked past end existing time */ _ns.seek( recordedDuration ); }
  1. Save all files and test the SWF in Flash (Control > Test Movie).

You have now created an application that can both broadcast and consume DVR-enabled video. You have even added controls for navigating the video with DVR functionality.

In the next walkthrough, you will test the functionality of your DVR player and see how you can replay moments from the live stream, as well as go to the beginning and navigate to the live broadcasting point of the stream.

 

Walkthrough 3: Testing the DVR-enabled live stream

 

 

In this walkthrough you will:

  • Publish a live DVR-enabled stream
  • Play back a DVR-enabled stream: play from beginning, go to live, instant replay, and seek within the DVR cache

Note: This walkthrough is a continuation from Walkthrough 2: Consuming a DVR-enabled live stream. You can either use the same files used in that walkthrough or open a fresh starting set from the {start files}/hands-on/DVR-Testing/start/ directory.

  1. If you don't already have the DVR-FlashConsumerPublisher movie running, test it. Click the Publish button to start recording the video.
  2. Roll over the second video display and click the Play button to view the recording stream.
  3. Now you can adjust the replay time with the NumericStepper. Click Replay to rewind the video the selected amount. Clicking View Live returns you to the end of the recorded stream (see Figure 5).

 

 

Walkthrough 3 illustrates the very basics of live DVR (publish and playback). It also leaves many issues exposed in the general workflow and management of a live and live DVR application.

With the addition of live DVR, the workflow for publishing, viewing, and managing a live event has expanded. The key points in the process to consider are the following:

  • Stream start: When the feed begins
  • Encode start: When the encoder begins
  • DVR start: When the server recording begins
  • Event start: When users can start viewing and how far back they can go

 

Where to go from here

Live DVR functionality has widespread uses and provides an extensible system on which to build. The basic implementation is very simple, because at its core it is really just extending the playback capabilities of recorded content to encompass content that is currently live as well.

With this enhancement, Adobe is taking steps to reaffirm its lead in the video streaming space and offer the mechanisms needed to help bridge the gap between television and the web. Although live DVR functionality does require Flash Media Interactive Server, because it needs to record video on the server, there are no new client Flash Player requirements to get this delivered to users. This feature may not be beneficial to everyone, but for the many use cases to which it pertains, live DVR offers great value without a major shift in existing process or management.

Part 2 of this series shows you how to implement the new DVRCast server-side sample application from Adobe, as well as stream and record content with Flash Media Live Encoder 3 and play back the live DVR content with the FLVPlayback 2.5 component.

 

 


More Like This

 

Encoding live video to H.264/AVC with Flash Player 11

Beginner's guide to streaming audio through Flash Media Server 3.5

Beginner's guide to dynamic streaming with Flash Media Server 3.5

Beginner's guide to using ActionScript 3.0 with Flash Media Server 3.5

Streaming AAC/MP3 files with Flash Media Server 3

Beginner's guide to installing Flash Media Server 3.5

Beginner's guide to streaming video with Flash Media Server 3.5

Protecting online video distribution with Adobe Flash media technology

Live dynamic streaming and DVR for non-developers

Setting a crossdomain.xml file for HTTP streaming