我正在使用6.0.2813(http://developer.longtailvideo.com/trac/)的JWPlayer源代码,虽然我有一个movieclip,但我将jwplayer类作为一个孩子添加,jwplayer创建自己作为主舞台的孩子,从而允许它扩展到舞台的边界,而不是我的影片剪辑(我想成为一个可调整大小/可拖动的容器)。
我向论坛寻求帮助,但是他们说他们从来没有打算这样做,并没有多大帮助。我希望有人熟悉源代码可以指出我的方向正确。
如何将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
}
}
}
并注意到RootReference.stage是作为孩子添加内容的地方。将玩家类对象作为displayObj发送的RootReference.stage = displayObj.stage;
我将其更改为RootReference.stage = MovieClip(root).gui.video_container;
然后在整个代码中使用了RootReference.stage.stageHeight
和RootReference.stage.stageWidth
,因此我将其切换为RootReference.stage.height
和RootReference.stage.width
。这得到它编译,现在视频在容器内,但视频的左上角是我的video_container中心的中心,视频没有调整到我的容器的大小,而是视频的大小。控制也完全搞砸了。
但我能够调整大小并移动视频
答案 0 :(得分:2)
我会解决你问题的 jwPlayer 部分,因为flash不是我的强项。
这里的问题是jwPlayer不是简单的Flash播放器,也是 HTML5多媒体播放器。
解决方案1:Flash对象中的SWFObject 嵌入式
由于 jwPlayer 已与SWFObject兼容,请将其(即swfobject.js)用作 介体 将player.swf
文件( aka jwPlayer )加载到您的Flash阶段。可以肯定的是, SWFObject 充当容器,并且将成为" 有界项"在你的舞台上,而不是直接使用 jwPlayer 。
以下是一个在线演示,说明此解决方案 , 使用简单的Flash视频播放器。
Flash Web Site with embedded SWFObject Logo Playing Music Video
Flash Web Site Documentation on swfObject
请注意,该Flash网站的HTML source page会将RockOnFlashLogo.swf显示为浏览器整个视口中显示的文件。看deeper,它是用 AS3 写的。
与 jwPlayer v4 不同,由于其安全性不高,internet上有许多想法可以将该版本嵌入到Flash网站中,我认为您是'会遇到当前 jwPlayer 许可检查,网页就绪事件监听器以及流行的插件集成问题......更不用说流视频内容可能引起的问题。
恕我直言,较新的 jwPlayer API和播放器旨在通过 网页安装 来使用。
解决方案2:Flash对象的SWFObject On-Top
此方法将 jwPlayer 视为如何使用;作为网页安装。我的动机来自Google Chrome Experiment | The Wilderness Downtown的在线演示。
该演示在主浏览器窗口的顶部放置了战略性同步的浏览器窗口。虽然主浏览器窗口负责, 所有窗口构成了整个体验 。同样的方法,但闪存风味,可以使用您当前的项目完成,效果非常好。
您的Flash对象负责且包含为jwPlayer 网页组件 分配的交互式frame。可以肯定的是, jwPlayer 的交互式框架可以接受重新定位(,例如,通过拖动框架边缘)和调整大小(例如,框架有resize-icon bottom-right ),然后将其转发到网页组件(,{{1} } )通过 SWFObject 标准嵌入技术(即位置和尺寸设置为player.swf
)。
以下是三个分层项目的网页的基本 横截面 :
黑色图层是网页的jQuery
。 红色图层是您的Flash对象,其中还包含 aqua 中显示的内置交互式框架。 绿色顶层是 jwPlayer HTML
文件的 SWFObject 。
以下是从jwPlayer到您的Flash对象的工作方式:
1。 网页 jwPlayer API 事件监听器处于活动状态,可以接受JavaScript。
2。 然后 jwPlayer API 接收' play'来自玩家的状态,更新玩家活动状态。
3。 播放器的播放器事件状态为 true ,因此触发器条件player.swf
言。
4. if
语句,然后将JavaScript 传输到您的Flash对象,表示播放模式为true。 强>
5. 您的Flash对象接收此播放事件的JavaScript, dims 强>舞台,少水色框架。
以下是从flash对象到jwPlayer的工作方式:
1。 当aqua 框架移至用户互动时舞台的左侧。
2。 您的 AS3 代码相应地移动了aqua 框架,而发送 >该位置的JavaScript。
3。 网页接收 JavaScript并调用函数将jwPlayer播放器置于新位置。
提示: 如果使用自定义 jwPlayer Skin ,请将皮肤主题合并到您的闪存中用于统一外观的对象。
此方案的好处是 jwPlayer 维持 100%完整性 ,而这两个Flash对象协同工作在您的网页上。没有黑客攻击,没有破损,没有不可预见的后果,也没有头痛......它正在使用标准的 jwPlayer API 和 AS3 标记。
将鼠标悬停在 jwPlayer 本身 100%jwPlayer ,间接绑定到您的Flash对象。
答案 1 :(得分:2)
根据您的书面评论, JW Player 将无法访问JavaScript
,并且将使用Firefox Source
专用的3D Game/Chat Engine
访问播放器外的任何DOM
元素,最佳解决方案是使用 JW Player Enterprise Edition 。
该解决方案可让您与 Marketing&工程部门,可提供交钥匙解决方案,将JW Player 集成到您自己的产品中。
答案 2 :(得分:2)
假设我的测试场景代表了您的用例,我认为我设法破解了一个解决方案。
该方法的要点是将RootReference.root
和RootReference.stage
替换为您控制的假舞台对象。因为大多数jwPlayer类引用那些静态变量而不是它们自己的root
和stage
变量,所以这似乎在大多数情况下都有效。结果是最复杂的问题是使用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
类中有一些细微的变化:
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
课程,以便更好地扩展和定位视频。
此外,它看起来像是视频的初始位置(至少在舞台视频中,你正在使用的是什么?)可以通过com.longtailvideo.jwplayer.media.VideoMediaProvider
类中的小编辑来纠正。将import somePackage.StageInterceptor;
添加到顶部的import语句,然后替换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的开源版本受Creative Commons许可管理,如上所述on their site:
JW Player 6 - 开源版 JW Player开放源代码版本的使用受Creative Commons许可证的约束。简而言之:
JW播放器开源 - 您可以使用,修改,复制和分发此版本,只要它用于非商业用途,您提供归属,并在类似许可下共享。 许可证摘要和全文可在此处找到:CC BY-NC-SA 3.0