7

我正在使用 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 是作为孩子添加的地方。RootReference.stage = displayObj.stage;播放器类对象作为 displayObj 发送的地方我将其更改为RootReference.stage = MovieClip(root).gui.video_container;

然后在整个代码中使用RootReference.stage.stageHeightand RootReference.stage.stageWidth,所以我将它切换到RootReference.stage.heightand RootReference.stage.width。这让它可以编译,现在视频在容器内,但视频的左上角在我的 video_container 的中心,并且视频的大小没有调整到我的容器的大小,而是视频的大小。控制也完全混乱。

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

4

3 回答 3

2

我将解决您问题的jwPlayer部分,因为 flash 不是我的强项。

这里的问题是jwPlayer不是一个简单的 Flash 播放器,也是一个HTML5 多媒体播放器


解决方案 1:嵌入Flash 对象中的SWFObject

由于jwPlayer已经与SWFObject兼容,因此使用它(即 swfobject.js)作为中介player.swf文件(也称为 jwPlayer)加载到您的 flash 阶段。可以肯定的是,SWFObject充当容器,将成为您舞台中的“有界项”,而不是直接使用jwPlayer

这是一个在线演示,说明了此解决方案,它使用的是一个简单的 Flash 视频播放器。

带有嵌入式 SWFObject 徽标的 Flash 网站 播放音乐视频
Flash 网站 关于 swfObject 的文档

请注意,该 Flash 网站的HTML 源页面将RockOnFlashLogo.swf显示为在浏览器整个视口中显示的文件。更深入地看,它是用AS3编写的。

jwPlayer v4不同,由于其安全性松懈,许多想法在互联网上浮出水面将该版本嵌入到 flash 网站中,我认为您会遇到当前jwPlayer许可证检查、网页就绪事件侦听器和流行插件集成的问题......提及流媒体视频内容可能出现的问题。

恕我直言,较新的jwPlayer API 和 Player 旨在通过网页安装使用。


解决方案 2:在Flash 对象之上的SWFObject

此方法处理jwPlayer的用途;作为网页安装。我的动力来自这个Google Chrome 实验的在线演示 | 荒野市中心

该演示将策略性同步的浏览器窗口置于主浏览器窗口的顶部。尽管主浏览器窗口负责,但所有窗口都构成了整个体验。同样的方法,但闪现风格,可以在您当前的项目中完成,并获得出色的结果。

您的 Flash 对象负责并包含在为 jwPlayer网页组件分配的交互式框架内。可以肯定的是,jwPlayer的这个交互式框架可以接受重定位例如,通过拖动框架边缘)和调整大小例如,框架具有resize-icon bottom-right ),然后通过SWFObject标准嵌入中继到网页组件()技术(用 设置的位置大小)。player.swfjQuery

这是三层项目的网页的基本横截面:

在此处输入图像描述

黑色层是HTML网页的。红色层是您的 Flash 对象,其中还包含以aqua显示的内置交互式框架。绿色的顶层是jwPlayer文件SWFObject 。 player.swf

这是从 jwPlayer 到您的 flash 对象的工作方式:

1.网页jwPlayer API事件监听器激活并且可以接受JavaScript。
2.然后jwPlayer API从播放器接收“播放”状态,更新播放器事件状态。
3.Player Event Status 为,因此触发条件if语句。
4.然后该if语句将JavaScript 传输到您的 flash 对象,表明播放模式为真。
5.你的 flash 对象接收到这个play事件的 JavaScript ,并使舞台变暗,水色框架。

以下是从 flash 对象到 jwPlayer 的工作方式:

1.水色相框移动到舞台左侧时有用户交互。
2.您的AS3代码相应地移动水色框架,同时发送该位置的 JavaScript。
3.网页接收JavaScript并调用函数将jwPlayer播放器定位到位置。

提示:如果使用自定义jwPlayer 皮肤,请将该皮肤主题合并到您的 flash 对象中以获得统一的外观。

这种情况的好处是jwPlayer保持100% 的完整性,而这两个 Flash 对象在您的网页上协同工作。没有黑客攻击,没有破损,没有不可预见的后果,也没有令人头疼的问题……这是标准的jwPlayer APIAS3标记在使用中。

将鼠标悬停在jwPlayer本身是100% jwPlayer,同时间接绑定到您的 flash 对象。

于 2012-12-16T10:14:07.697 回答
2

根据您的书面评论,JW Player将无权访问JavaScript并将使用Firefox Source它是专门的3D Game/Chat Engine ,无法访问DOM播放器之外的任何元素,最好的解决方案是使用JW Player Enterprise Edition

该解决方案将使您与营销和工程部门取得联系,该部门可以提供交钥匙解决方案,将 JW Player集成到您自己的产品中。

单击下面的图片,其中还包含许可信息: 在此处输入图像描述

于 2012-12-22T06:03:18.637 回答
2

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

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

jwPlayer 嵌入脚本引起了很多问题,所以开始时我切换到普通的基于 SWFObject 的嵌入,并在页面中添加了一个 JavaScript 函数,调用getFlashvars()该函数返回配置设置。然后,我将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

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类中的小编辑来纠正。添加import somePackage.StageInterceptor;到顶部的导入语句,然后替换此行(链接到源代码):

_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 的开源版本受知识共享许可管理,如其网站上所述:

JW Player 6 — 开源版 JW Player 开源版的使用受知识共享许可的约束。简而言之:

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

于 2012-12-22T15:14:36.087 回答