JWPlayer: trying to link a video player inside my container

I am using the JWPlayer source code for 6.0.2813 (http://developer.longtailvideo.com/trac/) and it seems that although I have a movie clip and I added the jwplayer class as a child, jwplayer creates itself as a child of the main scene. thereby allowing it to expand to the boundary of the scene, rather than my movie clip (which I want to be a scalable / draggable container) during my flash.

I asked the forums for help, but they said that they never planned it and didn't really help. I was hoping someone familiar with the source code could point me in the right direction.

How can I get JWPlayer to be contained in a movie clip?

Edit:

I moved forward a bit.

I found the RootReference class in com / longtailvideo / jwplayer / utils / RootReference.as

public function RootReference(displayObj:DisplayObject) { if (!RootReference.root) { RootReference.root = displayObj.root; RootReference.stage = displayObj.stage; try { Security.allowDomain("*"); } catch(e:Error) { // This may not work in the AIR testing suite } } } 

And I noticed that RootReference.stage is where things are added as a child. RootReference.stage = displayObj.stage; where the player class object is dispatched as displayObj, I changed it to RootReference.stage = MovieClip(root).gui.video_container;

Then throughout the entire code, RootReference.stage.stageHeight and RootReference.stage.stageWidth used, so I switched it to RootReference.stage.height and RootReference.stage.width . This made it compile, and now the video is inside the container, but the upper left video center is in the center of my video_container, and the video does not change to the size of my container, but rather the size of the video. Also, the controls are completely confused.

But I managed to resize and move the video around

+7
source share
3 answers

Assuming my test scripts are representative of your use cases, I think I managed to hack the work.

The essence of the approach is to replace RootReference.root and RootReference.stage with a fake stage object that you control. Since most jwPlayer classes reference these static variables instead of their root and stage variables, this seems to work, for the most part. What turned out to be the hardest problem was working with Stage.stageVideo objects, which I think are hardware accelerated video objects. They are always attached to stage and, therefore, are incompatible with the object of the fake scene. The main problem with this is positioning, and I basically developed it, but there is another glitch that I will describe later , but now it should be fine.

Embedding the jwPlayer script caused a lot of problems, so for a start I switched to the usual embedding based on SWFObject and added a javascript function to the page named getFlashvars() , which returned the configuration settings. Then I changed the com.longtailvideo.jwplayer.utils.Configger.loadExternal() method to the following:

 private function loadExternal():void { if (ExternalInterface.available) { try { //var flashvars:Object = ExternalInterface.call("jwplayer.embed.flash.getVars", ExternalInterface.objectID); var flashvars:Object = ExternalInterface.call("getFlashvars"); if (flashvars !== null) { // TODO: add ability to pass in JSON directly instead of going to/from a string for (var param:String in flashvars) { setConfigParam(param, flashvars[param]); } dispatchEvent(new Event(Event.COMPLETE)); return; } } catch (e:Error) {} } } 

Something you probably don't have to deal with if you're not using a web page.

The fake stage class is called StageInterceptor and is a singleton. To apply it, minor changes RootReference occurred in the RootReference class:

 package com.longtailvideo.jwplayer.utils { import flash.display.DisplayObject; import flash.display.Stage; import flash.system.Security; // added -------- import somePackage.StageInterceptor; /** * Maintains a static reference to the stage and root of the application. * * @author Pablo Schklowsky */ /* Modified for a stackoverflow question: http://stackoverflow.com/questions/13325318/jwplayer-trying-to-bound-the-video-player-inside-my-own-container */ public class RootReference { /** The root DisplayObject of the application. **/ public static var root:DisplayObject; // altered -------- /** A reference to the stage. **/ private static var _stage:StageInterceptor; // altered -------- public static function get stage():StageInterceptor { return _stage; } public function RootReference(displayObj:DisplayObject) { if (!RootReference.root) { // altered -------- RootReference.root = StageInterceptor.singleton; RootReference._stage = StageInterceptor.singleton; try { Security.allowDomain("*"); } catch(e:Error) { // This may not work in the AIR testing suite } } } } } 

In addition, I removed the set set stage() method from the class.

In the document class, I have the following code. The MouseEvent.CLICK handler is designed to test the positioning and recalibration of a movie. The only thing you really need is the first few lines:

 // add StageInterceptor to the display tree addChild(StageInterceptor.singleton); // add the jwPlayer: var p:Player = new Player(); StageInterceptor.singleton.addChild(p); // for testing only: stage.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void { var stg:StageInterceptor = StageInterceptor.singleton; if (e.altKey) { // click + alt: ignored (so can play, etc) return; } else if (e.shiftKey) { // click + shift: resizes stg.width = e.stageX - stg.x; stg.height = e.stageY - stg.y; } else { // click: moves video stg.x = e.stageX; stg.y = e.stageY; } }); 

I put StageInterceptor in somePackage package. It looks like this:

 package somePackage { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.InteractiveObject; import flash.display.Shape; import flash.display.Sprite; import flash.events.Event; import flash.geom.Point; import flash.geom.Rectangle; import flash.media.StageVideo; public class StageInterceptor extends Sprite { private static var _singleton:StageInterceptor = new StageInterceptor(); public static function get singleton():StageInterceptor { return _singleton; } private var _bg:Bitmap; public function StageInterceptor() { super(); scrollRect = new Rectangle(0, 0, 500, 500); var bmpData:BitmapData = new BitmapData(500, 500, false, 0); _bg = new Bitmap(bmpData); _bg.alpha = 0.1; _bg.cacheAsBitmap = true; addChild(_bg); if (stage) { initOnStage(); } else { addEventListener(Event.ADDED_TO_STAGE, initOnStage); } } private function initOnStage(e:Event = null):void { if (e) { removeEventListener(Event.ADDED_TO_STAGE, initOnStage); } stage.addEventListener(Event.RESIZE, onStageResized); } private function onStageResized(e:Event):void { e.stopImmediatePropagation(); dispatchEvent(new Event(Event.RESIZE)); updateStageVids(); } public function updateStageVids():void { if (stage.stageVideos.length > 0) { for each (var sv:StageVideo in stage.stageVideos) { if (!sv.videoWidth || !sv.videoHeight) { continue; } var rect:Rectangle = stretch(sv.videoWidth, sv.videoHeight, width, height); rect.x = Math.max(0, x + 0.5 * (width - rect.width)) rect.y = Math.max(0, y + 0.5 * (height - rect.height)); sv.viewPort = rect; } } } override public function get width():Number { return scrollRect.width; } override public function set width(value:Number):void { if (value != width) { _bg.width = value; scrollRect = new Rectangle(0, 0, value, scrollRect.height); dispatchEvent(new Event(Event.RESIZE)); updateStageVids(); } } override public function set height(value:Number):void { if (value != height) { _bg.height = value; scrollRect = new Rectangle(0, 0, scrollRect.width, value); dispatchEvent(new Event(Event.RESIZE)); updateStageVids(); } } override public function get height():Number { return scrollRect.height; } public function get stageWidth():Number { return scrollRect.width; } public function get stageHeight():Number { return scrollRect.height; } public function get scaleMode():String { return stage.scaleMode; } public function set scaleMode(value:String):void { stage.scaleMode = value; } public function get displayState():String { return stage.displayState; } public function set displayState(value:String):void { stage.displayState = value; } public function get focus():InteractiveObject { return stage.focus; } public function set focus(value:InteractiveObject):void { stage.focus = value; } public function get stageVideos():* { return stage.stageVideos; } override public function set x(value:Number):void { if (value != x) { super.x = value; updateStageVids(); } } override public function set y(value:Number):void { if (value != y) { super.y = value; updateStageVids(); } } /** * Copied from com.longtailvideo.jwplayer.utils.Stretcher, modified to only * do 'uniform' stretch and to return a Rectangle class. **/ public static function stretch(elmW:Number, elmH:Number, availW:Number, availH:Number):Rectangle { var scale:Number = Math.min(availW / elmW, availH / elmH); elmW = Math.round(elmW * scale); elmH = Math.round(elmH * scale); return new Rectangle(0, 0, elmW, elmH); } } } 

The problem remains with the positioning of the video instances when they are initialized. I think just calling StageInterceptor.singleton.updateStageVids(); at the right point will do the trick, but I'm not sure. The following is a description of how this has been described.

I'm not sure how much this will work if you are not using stageVideo . But, with luck, it will change the situation in the right direction.

Edit:

I updated the StageInterceptor class to improve performance scaling and video positioning.

Also, it looks like the starting position of the video (at least when it's stageVideo, is that what you are using?) Can be fixed by a small change in the class com.longtailvideo.jwplayer.media.VideoMediaProvider . By adding import somePackage.StageInterceptor; into the import statements at the top and then replacing this line (link to source):

_stage.viewPort = new Rectangle(_media.x,_media.y,_media.width,_media.height);

To:

StageInterceptor.singleton.updateStageVids();

So the method looks like this:

 /** Resize the video or stage.**/ override public function resize(width:Number, height:Number):void { if(_media) { Stretcher.stretch(_media, width, height, _config.stretching); if (_stage) { //_stage.viewPort = new Rectangle(_media.x,_media.y,_media.width,_media.height); StageInterceptor.singleton.updateStageVids(); } } } 

This should do the trick, but I have not tested it for non stageVideos. And this update also assumes that you play the video gradually without using RTMP.

Edit:

To enable and resize the player with videos without a scene, but still loading gradually, the contents of the com.longtailvideo.jwplayer.view.View.resizeMasker() method must either be commented out or deleted:

 protected function resizeMasker():void { /* if (_displayMasker == null) setupDisplayMask(); _displayMasker.graphics.clear(); _displayMasker.graphics.beginFill(0, 1); _displayMasker.graphics.drawRect(_components.display.x, _components.display.y, _player.config.width, _player.config.height); _displayMasker.graphics.endFill(); */ } 

I also want to mention that the open source version of jwPlayer is managed under a Creative Commons license, as indicated on its website :

JW Player 6 - open source version Use of the open source version of JW Player is governed by a Creative Commons license. In short:

JW Player Open Source - you can use, modify, copy and distribute this version, if it is used for non-commercial use, you provide attribution and share it under a similar license. A summary of the license and the full text can be found here: CC BY-NC-SA 3.0

+2
source

I will consider the jwPlayer part of your question, since flash is not my forte.

The problem here is jwPlayer - not just a flash player, but also an HTML5 Multimedia Player .


Solution 1: SWFObject embedded in your Flash object

Since jwPlayer is already compatible with SWFObject , use this (i.e. swfobject.js) as an intermediary to download the player.swf file ( aka jwPlayer ) to your flash stage. Of course, SWFObject acts like a container and will be a "limited item" at your stage, as opposed to using jwPlayer .

Here's an online demo of this solution other than using a simple Flash video player.

Flash website with integrated SWFObject logo Play music video
Flash site documentation on swfObject

Pay attention to the HTML source page for this RockOnFlashLogo.swf flash website as the file displayed in the entire browser view. Looking deeper , it is written in AS3 .

Unlike jwPlayer v4 , where many ideas are posted on the internet to embed this version on flash sites due to its intermittent security, I think you will have problems with the current jwPlayer license check , Ready List Listeners web page and the popular integration with plugins ... not to mention the problems that may arise from streaming video content.

IMHO, the new jwPlayer API and Player are designed to be used by setting up a web page .


Solution 2: SWFObject Top of your Flash Object

This method considers jwPlayer how it should be used; like setting a web page. My motivation came from this online demo for the Google Chrome Experiment | The Wilderness Downtown .

This demo places strategically synchronized browser windows on top of the main browser window. Although the main browser window is responsible , all windows make up the whole experience . The same method, but with flash seasonings, can be performed with your current project with excellent results.

Your Flash object is responsible and contains an interactive frame that is allocated for the jwPlayer web page component . Of course, this interactive frame for jwPlayer can take a move (for example, by dragging the frame borders) and resize (for example, the frame has a resize icon in the lower right ), which is then transferred to the web page component (i.e. player.swf ) using standard SWFObject implementation technologies (i.e. location and size with jQuery )).

Here is the basic cross section of a web page for three-layer elements:

enter image description here

Black is the HTML web page. Red is your Flash object, which also contains the built-in interactive frame shown in aqua . The top layer is green - this is SWFObject for the jwPlayer player.swf file .

Here's how it works with jwPlayer on your Flash object:

1. The jwPlayer API web page has an event listener and can accept JavaScript.
2. Then, the jwPlayer API receives the player status from the player, updates the player status.
3. The event state of the player is true for playback, and therefore calls a conditional if statement.
4. This if then passes JavaScript to your Flash object, indicating that the playback mode is true.
5. Your Flash object receives this JavaScript from play , and dims - the scene, less aqua frame.

Here's how it will work with your Flash object on jwPlayer:

1. In frame 2. Your AS3 code moves the frame

Tip. . If you are using custom jwPlayer Skin , include this skin theme in your Flash object for a uniform > Look.

The advantage of this scenario is that jwPlayer maintains 100% integrity , while both of these flash objects work in tandem on your web page. No hacks, no breakdowns, unforeseen consequences and no headaches ... this is the standard jwPlayer API and AS3 markup.

Hovering over jwPlayer is 100% jwPlayer , but is tied to the Flash object indirectly.

+2
source

In your written comments that JW Player will not have any JavaScript access and will use Firefox Source , which is a specialized 3D Game/Chat Engine without access to any DOM elements outside the player, the best solution is to use JW Player Enterprise Edition.

This solution will connect you with the marketing and engineering department, which can provide a turnkey solution for incorporating JW Player into your own product.

Click on the image below that includes licensing information: enter image description here

+2
source

All Articles