JWPlayer:尝试将视频播放器绑定在我自己的容器中

Par*_*roX 7 flash actionscript actionscript-3 jwplayer

我正在使用6.0.2813(http://developer.longtailvideo.com/trac/)的JWPlayer源代码.虽然我有一个movieclip并且我将jwplayer类作为一个孩子添加,但jwplayer创建自己为主舞台的一个孩子,因此允许它扩展到舞台的边界,而不是我的flashclip(我想成为一个可调整大小/可拖动的容器).

我向论坛寻求帮助,但他们说他们从来没有这样做过,并没有多大帮助.我希望有人熟悉源代码可以指出我正确的方向.

如何将JWPlayer包含在movieclip中?

编辑:

我取得了一些进展.

我在com/longtailvideo/jwplayer/utils/RootReference.as中找到了RootReference类

        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
                }
            }
        }
Run Code Online (Sandbox Code Playgroud)

并注意到RootReference.stage是作为孩子添加内容的地方.RootReference.stage = displayObj.stage;将播放器类对象作为displayObj发送的地方我将其更改为RootReference.stage = MovieClip(root).gui.video_container;

然后,整个代码RootReference.stage.stageHeightRootReference.stage.stageWidth使用,所以我就切换到RootReference.stage.heightRootReference.stage.width.这得到它编译,现在视频在容器内,但视频的左上角是我的video_container中心的中心,视频没有调整到我的容器的大小,而是视频的大小.控件完全搞砸了.

但我能够调整大小并移动视频

tif*_*fon 2

假设我的测试场景代表了您的用例,我想我设法解决了这个问题。

\n

该方法的要点是用您控制的虚假舞台对象替换RootReference.root和。RootReference.stage因为大多数 jwPlayer 类引用这些静态变量而不是它们自己的rootstage变量,所以这在大多数情况下似乎是有效的。最终成为最复杂的问题是处理对象Stage.stageVideo,我认为这些对象是硬件加速视频对象。它们始终附加到stage,因此与假舞台对象不兼容。这些问题的主要问题是定位,我已经解决了大部分问题,但仍然存在一个小故障,我将在稍后描述,但现在应该没问题了。

\n

jwPlayer 嵌入脚本导致了很多问题,因此开始时我切换到普通的基于 SWFObject 的嵌入,并向调用的页面添加了一个 javascript 函数getFlashvars()以返回配置设置。然后,我将com.longtailvideo.jwplayer.utils.Configger.loadExternal()方法更改为以下:

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

如果不使用网页,您可能不必处理这些问题。

\n

假舞台类被称为StageInterceptor并且是一个单例。为了应用它,对类进行了一些细微的更改RootReference

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

另外,我set stage()从类中删除了 setter 方法。

\n

在文档类中,我有以下代码。处理程序MouseEvent.CLICK用于测试影片的定位和调整大小。您唯一真正需要的是前几行:

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

我放进StageInterceptor了包裹里somePackage。它看起来像这样:

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

剩下的问题与视频实例初始化时的定位有关。我认为只需StageInterceptor.singleton.updateStageVids();在正确的时间点调用即可解决问题,但我不确定。下面的编辑介绍了如何解决这个问题。

\n

我不确定如果您不使用stageVideo. 但是,如果幸运的话,这将使事情朝着正确的方向发展。

\n

编辑:

\n

我已经更新了该类,StageInterceptor以便更好地缩放和定位视频。

\n

另外,看起来视频的初始位置(至少当它是 stageVideo 时,这是您正在使用的吗?)可以通过类中的小编辑来纠正com.longtailvideo.jwplayer.media.VideoMediaProvider。添加import somePackage.StageInterceptor;到顶部的导入语句,然后替换此行(链接到源代码):

\n

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

\n

到:

\n

StageInterceptor.singleton.updateStageVids();

\n

所以该方法看起来像:

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

这应该可以解决问题,但我还没有对非 stageVideos 进行测试。而且,此更新还假设您正在渐进式播放视频,而不是使用 RTMP 媒体。

\n

编辑:

\n

要启用非 StageVideo 视频的移动和调整播放器大小,但仍逐步加载,com.longtailvideo.jwplayer.view.View.resizeMasker()需要注释掉或删除该方法的内容:

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

我还想提一下 jwPlayer 的开源版本受知识共享许可的约束,如其网站上所述所述:

\n
\n

JW Player 6 \xe2\x80\x94 开源版\nJW Player 开源版的使用受知识共享许可证的约束。简而言之:

\n

JW Player 开源 - 您可以使用、修改、复制和分发此版本,只要它用于非商业用途、您提供归属并在类似许可证下共享。\n许可证摘要和全文可以在在这里找到:CC BY-NC-SA 3.0

\n
\n