» Fig Leaf Software Home

We've Got You Covered.

Thursday, November 13, 2014

Building a Sencha Touch Wrapper for the Brightcove Video Player

Building a Sencha Touch Wrapper for the Brightcove Video Player

We decided that it would be a good idea to develop a Brightcove Video Player object for future use in our Sencha Touch projects. The Brightcove Video Cloud service allows users to maintain and control the distribution of videos they upload. One aspect of the player that makes it useful for web development is that it will create itself as either a Flash or HTML5 object, depending on what the current browser supports.

The component has two main config properties: the playerKey and the playerID. To get these, make an account at brightcove.com and go to the Publishing tab. If you want to load a video when the player initializes, grab a videoID from the Media tab. Additional functions of the Brightcove API require Player and Experience objects, which can be obtained by calling the getPlayer() and getBrightcoveExperience() methods of this class.

In order to make sure that the API fully loads before anything can be done, the initialization work is done after the container is rendered. This is done in the handler for the 'painted' event:

1:  onBCPPainted: function(element, eOpts) {  
2:      if (typeof(brightcove) == 'undefined') {  
3:         this.setMasked({  
4:          xtype: 'loadmask',  
5:          message: 'Loading Brightcove API...',  
6:          indicator: true  
7:         });  
8:         Ext.Loader.loadScriptFile('http://admin.brightcove.com/js/BrightcoveExperiences.js',  
9:          function() {  
10:           this.setMasked(false);  
11:           this.createPlayer();  
12:          },  
13:          function() {  
14:           alert("Failed to load API");  
15:          },  
16:          this  
17:         );  
18:        } else {  
19:         this.createPlayer();  
20:        }  
21:        bp = this;  
22:    },  

First, this checks if the Brightcove API is already loaded. If it is, it proceeds to call the createPlayer() method. If not, it loads the script file and asynchronously calls createPlayer() after the file has been loaded. In order to show the player within a Sencha Touch container, we had to set its HTML to that of the player object and render it.
1:  createPlayer: function() {  
2:        console.log("SCOPE: ", this);  
3:        onTemplateLoadHandler = function(experienceID) {  
4:         bp.onTemplateLoad(experienceID);  
5:        };  
6:        onTemplateReadyHandler = function(evt) {  
7:         bp.onTemplateReady(evt);  
8:        };  
9:        this.htmlString = ''.concat('<object id="{0}" class="BrightcoveExperience">',  
10:         '<param name="bgcolor" value="{1}\" /><param name="width"',  
11:         'value="{2}" /><param name="height" value="{3}" />',  
12:         '<param name="playerID" value="{4}" />',  
13:         '<param name="playerKey\" value="{5}" />',  
14:         '<param name="isVid\" value="{6}" />',  
15:         '<param name="isUI" value="true" />',  
16:         '<param name="dynamicStreaming" value="{7}" />',  
17:         '<param name="@videoPlayer" value="{8}" />',  
18:         '<param name="includeAPI" value="true" />',  
19:         '<param name="templateLoadHandler" value="onTemplateLoadHandler" />',  
20:         '<param name="templateReadyHandler" value="onTemplateReadyHander" />');  
21:        Ext.Viewport.on('orientationchange', 'onOrientationChange', this, {  
22:         buffer: 50  
23:        });  
24:        this.setMasked({  
25:         xtype: 'loadmask',  
26:         message: 'Loading Video...',  
27:         indicator: true  
28:        });  
29:        this.setHtml(Ext.String.format(this.htmlString,  
30:         this.getPlayerName(),  
31:         this.getPlayerBgcolor(),  
32:         this.element.getWidth(),  
33:         this.element.getHeight(),  
34:         this.getPlayerID(),  
35:         this.getPlayerKey(),  
36:         this.getIsVid(),  
37:         this.getDynamicStreaming(),  
38:         this.getVideoID()));  
39:        brightcove.createExperiences();  
40:        this.setMasked(false);  
41:    },  

There are also declared handler's for when the player is loaded and when it is ready to be used. The onTemplateLoad event fires when the Brightcove player is loaded, and instantiates the brightcoveExperience and player fields. It also adds an event listener (A Brightcove event, not a Sencha Touch event) for when the video is played for the first time. This will be important later. The onTemplateReady function simply logs that the player is ready for use.

1:    onTemplateLoad: function(experienceID) {  
2:        var BCExperience = (brightcove.api.getExperience(experienceID));  
3:        this.setBrightcoveExperience(BCExperience);  
4:        var APIModules = (brightcove.api.modules.APIModules);  
5:        var player = BCExperience.getModule(APIModules.VIDEO_PLAYER);  
6:        this.setPlayer(player);  
7:        this.getPlayer().addEventListener(brightcove.api.events.MediaEvent.BEGIN,  
8:         function() {  
9:          console.log('Event media begin');  
10:          if (typeof bp.currentPosition !== "undefined") {  
11:           player.seek(bp.currentPosition);  
12:          }  
13:         });  
14:    },  
15:    onTemplateReady: function(evt) {  
16:      console.log('template ready');  
17:      console.log("SCOPE: " , this);  
18:    }  

We hit a specific challenge when it came to mobile users rotating the device. We initially thought that re-rendering the player with the new width and height would be enough, but that resulted in the player being completely wiped. Instead, we had to create a parent container for the video player. When the player detects a device rotation, it calls its onOrientationChange method. This grabs the current time of the video (if it has been played) and passes it along to the onParentOrientationChange of the parent container along with the new width and height. The reason it checks if the user is using iOS is because iOS devices launch their video in Quicktime by default, which already supports device rotation with seamless playback.

1:    onOrientationChange: function(scope, newOrientation, width, height, eOpts) {  
2:       this.getPlayer().getIsPlaying(function(currentlyPlaying) {  
3:         if (!Ext.os.is('iOS') || !currentlyPlaying) {  
4:          var currentPosition;  
5:          // debugger;  
6:          this.getPlayer().getVideoPosition(false, function(r) {  
7:           console.log(r);  
8:           bp.getParent().parentOrientationChange({  
9:            currentPosition: r,  
10:            html: Ext.String.format(bp.htmlString,  
11:             bp.getPlayerName(),  
12:             bp.getPlayerBgcolor(),  
13:             width,  
14:             height,  
15:             bp.getPlayerID(),  
16:             bp.getPlayerKey(),  
17:             bp.getIsVid(),  
18:             bp.getDynamicStreaming(),  
19:             bp.getVideoID()),  
20:           });  
21:          });  
22:         }  
23:        });  
24:    },  

The parentOrientationChange method destroys the current video and replaces it with a new player with the updated dimensions. Going back to line 10 of onTemplateLoad, it checks if the current object has a field variable called 'currentPosition', which is only given to it by onOrientationChange. If it is, then it tells the player to start playback at that position. This way, even though we are completely destroying and recreating the video player, users can still resume playback at the point where they rotated the device.

1:    parentOrientationChange: function(bcPlayerConfigs) {  
2:      this.remove(this.down('BCPlayer'),true); 
3:      var newPlayer = Ext.create('MyApp.view.BrightcovePlayer', bcPlayerConfigs);  
4:      this.add(newPlayer);  
5:      brightcove.createExperiences();  
6:    }  

No comments:

Post a Comment

About Us

Fig Leaf Software is an award-winning team of imaginative designers, innovative developers, experienced instructors, and insightful strategists.

For over 20 years, we’ve helped a diverse range of clients...

Read More

Contact Us


Fig Leaf Software

1400 16th Street NW
Suite 450
Washington, DC 20036