actionscript-3 - JWPlayer:试图将视频播放器绑定(bind)在我自己的容器中

标签 actionscript-3 flash actionscript jwplayer

我正在使用 6.0.2813 (http://developer.longtailvideo.com/trac/) 的 JWPlayer 源代码,看起来即使我有一个电影剪辑并且我在小时候添加了 jwplayer 类,jwplayer 将自己创建为主舞台的一个子级,因此允许它扩展到舞台的边界,而不是我的 flash 中的电影剪辑(我想成为一个可调整大小/可拖动的容器)。

我向论坛寻求帮助,但他们说他们从来没有这样打算,也没有太大帮助。我希望熟悉源代码的人能指出我正确的方向。

如何让 JWPlayer 包含在影片剪辑中?

编辑:

我取得了一点进展。

我在 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
                }
            }
        }

并注意到 RootReference.stage 是作为 child 添加的地方。 RootReference.stage = displayObj.stage;播放器类对象作为 displayObj 发送的位置我将其更改为 RootReference.stage = MovieClip(root).gui.video_container;
然后整个代码RootReference.stage.stageHeightRootReference.stage.stageWidth被使用所以我把它切换到RootReference.stage.heightRootReference.stage.width .这让它可以编译,现在视频在容器内,但视频的左上角在我的 video_container 的中心,并且视频的大小没有调整到我的容器的大小,而是视频的大小。控制也完全困惑。

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

最佳答案

假设我的测试场景代表了您的用例,我想我设法解决了问题。
该方法的要点是替换 RootReference.rootRootReference.stage使用您控制的假舞台对象。因为大多数 jwPlayer 类都引用那些静态变量而不是它们自己的 rootstage变量,这似乎在大多数情况下都有效。最终成为最复杂的问题是使用 Stage.stageVideo对象,我认为是硬件加速的视频对象。这些总是附加到 stage因此与假舞台对象不兼容。这些的主要问题是定位,我基本上已经解决了,但仍有一个故障,我稍后会描述,但现在应该没问题。
jwPlayer 嵌入脚本引起了很多问题,所以开始我切换到普通的基于 SWFObject 的嵌入,并在页面中添加了一个名为 getFlashvars() 的 javascript 函数。返回配置设置。然后,我更改了 com.longtailvideo.jwplayer.utils.Configger.loadExternal()方法如下:

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) {}
    }
}
如果不使用网页,您可能不必处理这些问题。
假舞台类叫StageInterceptor并且是单例。为了应用它,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
                }
            }
        }
    }
}
另外,我删除了 set stage()类中的setter方法。
在文档类中,我有以下代码。 MouseEvent.CLICK处理程序用于测试电影的定位和重新调整大小。您真正需要的只是前几行:
// 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;
    }
});
我把 StageInterceptor包装内somePackage .它看起来像这样:
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);
        }
    }
}
剩下的问题与初始化视频实例时的定位有关。我想只需调用 StageInterceptor.singleton.updateStageVids();在正确的地方会成功,但我不确定。下面的编辑介绍了如何解决这个问题。
如果您不使用 stageVideo,我不确定这将如何运作.但是,如果运气好的话,这将使事情朝着正确的方向发展。
编辑:
我更新了 StageInterceptor类可以更好地缩放和定位视频。
此外,看起来视频的初始位置(至少当它是 stageVideo 时,是你正在使用的吗?)可以通过 com.longtailvideo.jwplayer.media.VideoMediaProvider 中的小编辑来纠正。类(class)。添加 import somePackage.StageInterceptor;到顶部的导入语句,然后替换 this line (link to source):_stage.viewPort = new Rectangle(_media.x,_media.y,_media.width,_media.height);到:StageInterceptor.singleton.updateStageVids();所以方法看起来像:
/** 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();
        }
    }
}
这应该可以解决问题,但我还没有为非 stageVideos 测试过它。而且,此更新还假设您正在逐步播放视频,而不是使用 RTMP 媒体。
编辑:
要使用非 StageVideo 视频启用播放器的移动和调整大小,但仍会逐渐加载, com.longtailvideo.jwplayer.view.View.resizeMasker() 的内容方法需要被注释掉或删除:
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();
    */
}
我还想提一下 jwPlayer 的开源版本受知识共享许可管理,如 on their site 所述。 :

JW Player 6 — Open Source Edition The use of the JW Player Open Source edition is governed by a Creative Commons license. In short:

JW Player Open Source - You can use, modify, copy, and distribute this edition as long as it's for non-commercial use, you provide attribution, and share under a similar license. The license summary and full text can be found here: CC BY-NC-SA 3.0

关于actionscript-3 - JWPlayer:试图将视频播放器绑定(bind)在我自己的容器中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13325318/

相关文章:

flash - 有没有可以被Flash和Silverlight无缝加载的视频编解码器?

actionscript-3 - As3Iso : Why use a secondary display list?

jquery - 常见补间/缓动函数的在线图表?

ios - 闪存临 CS6 : Publishing for iOS using AIR - "Could not access digital certificate"

ActionScript 中的 JavaScript 警报

flash - 如何制作 Adob​​e Flash/Flex 图表组件 "from scratch"(使用 AS3/MXML)?

xml - 将 XML 节点转换为 MovieClip

actionscript-3 - 为什么要使用 MXML?

asp.net - 如何在 Web 应用程序客户端录制音频并将其保存在 Web 服务器中?

flash - 为什么Flash要乘以8?