我正在使用 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.stageHeight
和 RootReference.stage.stageWidth
被使用所以我把它切换到RootReference.stage.height
和 RootReference.stage.width
.这让它可以编译,现在视频在容器内,但视频的左上角在我的 video_container 的中心,并且视频的大小没有调整到我的容器的大小,而是视频的大小。控制也完全困惑。但我能够调整视频大小和移动视频
最佳答案
假设我的测试场景代表了您的用例,我想我设法解决了问题。
该方法的要点是替换 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
中有一些细微的变化。类(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/