actionscript-3 flash actionscript jwplayer

actionscript 3 - JWPlayer: intentando encuadernar el reproductor de video dentro de mi propio contenedor



actionscript-3 flash (3)

Estoy usando el código fuente de JWPlayer para 6.0.2813 (http://developer.longtailvideo.com/trac/) y parece que a pesar de que tengo un clip de película y agregué la clase jwplayer como un niño, el jwplayer se crea a sí mismo como un hijo del escenario principal, lo que le permite expandirse al límite del escenario y no a mi clip de película (que quiero ser un contenedor redimensionable / arrastrable) en mi flash.

Pedí ayuda a los foros, pero me dijeron que nunca lo habían pensado así y que no fueron de mucha ayuda. Esperaba que alguien familiarizado con el código fuente pudiera apuntarme en la dirección correcta.

¿Cómo puedo obtener el JWPlayer contenido en un clip de película?

Editar:

Hice un poco de progreso.

Encontré la clase RootReference en com / longtailvideo / jwplayer / utils / RootReference.as

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

Y notó que RootReference.stage es donde las cosas se agregan como un niño. RootReference.stage = displayObj.stage; donde el objeto de clase del jugador se envía como displayObj lo cambié para ser RootReference.stage = MovieClip(root).gui.video_container;

Luego, a lo largo del código RootReference.stage.stageHeight y RootReference.stage.stageWidth se utilizó, así que lo RootReference.stage.height a RootReference.stage.height y RootReference.stage.width . Esto lo compiló y ahora el video está dentro del contenedor, pero la parte superior izquierda del video está centrada en el centro de mi video_container y el video no se redimensiona al tamaño de mi contenedor, sino al tamaño del video. Además, los controles están completamente desordenados.

Pero pude cambiar el tamaño y mover el video


Me dirigiré a la parte jwPlayer de tu pregunta ya que el flash no es mi fuerte.

El problema aquí es que jwPlayer no es un simple reproductor de flash, sino también un reproductor multimedia HTML5 .

Solución 1: SWFObject incrustado en su objeto Flash

Como jwPlayer ya es compatible con SWFObject , utilícelo (es decir, swfobject.js) como mediador para cargar el archivo player.swf ( también conocido como jwPlayer ) en su etapa de flash. Para estar seguro, SWFObject actúa como un contenedor y será el " elemento delimitado " en su escenario, en lugar de usar jwPlayer directamente.

Aquí hay una demostración en línea que ilustra esta solución, excepto que está usando un reproductor de video flash simple.

Sitio web Flash con el logotipo SWFObject incorporado Reproducción de videos musicales
Documentación del sitio web de Flash en swfObject

Tenga en cuenta que la página fuente HTML para ese sitio web flash muestra RockOnFlashLogo.swf como el archivo que se muestra en la vista completa de los navegadores. Mirando más profundo , está escrito en AS3 .

A diferencia de jwPlayer v4, donde flotaron muchas ideas en Internet para insertar esa versión en los sitios web flash debido a su seguridad laxa, creo que tendrás problemas con la comprobación actual de licencias de jwPlayer, los escuchas de eventos listos para la página web y la popular integración de complementos ... no mencionar problemas que pueden surgir del contenido de video de transmisión.

En mi humilde opinión, la API y el reproductor jwPlayer más nuevos están destinados a ser utilizados a través de la instalación de páginas web .

Solución 2: SWFObject en la parte superior de su objeto Flash

Este método trata a jwPlayer cómo debía ser usado; como una instalación de página web. Mi motivación vino de esta demostración en línea para Google Chrome Experiment | The Wilderness Downtown .

Esa demostración coloca ventanas del navegador sincronizadas estratégicamente en la parte superior de la ventana principal del navegador. Aunque la ventana principal del navegador está a cargo, todas las ventanas conforman toda la experiencia . El mismo método, pero con sabor a flash , se puede hacer con su proyecto actual con excelentes resultados.

Su objeto Flash está a cargo y contiene dentro de un marco interactivo que se asigna para el componente de página web jwPlayer. Para estar seguro, este marco interactivo para jwPlayer puede aceptar reubicación ( por ejemplo, al arrastrar los bordes del marco ) y cambiar el tamaño ( p. Ej., El marco tiene tamaño-icono inferior-derecho ) que luego se retransmite al componente de la página web ( es decir, player.swf ) Técnicas de inserción estándar de SWFObject ( es decir, ubicación y tamaño establecidos con jQuery ).

Aquí hay una sección transversal básica de una página web para tres elementos en capas:

La capa negra es el HTML de la página web. La capa roja es su objeto flash que también contiene el marco interactivo incorporado que se muestra en aqua . La capa superior verde es el SWFObject para el archivo player.swf de player.swf .

Así es como funcionaría desde jwPlayer hasta su objeto flash:

1. Página web jwPlayer API tiene activada la función de escucha de eventos y puede aceptar JavaScript.
2. Luego la API de jwPlayer recibe el estado de "reproducción" del jugador, actualiza el estado del evento del jugador.
3. El estado del evento del jugador es verdadero para Play y, por lo tanto, activa la sentencia if condicional.
4. Esa declaración if luego transmite JavaScript a su objeto flash, lo que indica que el modo de reproducción es verdadero.
5. Su objeto flash recibe este JavaScript del evento play y atenúa el escenario, menos el marco acuático.

Así es como funcionaría desde su objeto flash a jwPlayer:

1. El marco acuático tiene interacción con el usuario cuando se mueve al lado izquierdo del escenario.
2. Su código AS3 mueve el marco de agua en consecuencia, al tiempo que envía el código JavaScript de esa ubicación.
3. La página web recibe JavaScript e invoca la función para posicionar el reproductor jwPlayer en una nueva ubicación.

Consejo: si usa un skin personalizado de jwPlayer , incorpore ese tema de piel en su objeto flash para una apariencia uniforme .

El beneficio de este escenario es que jwPlayer mantiene una integridad del 100%, mientras que estos dos objetos flash funcionan en conjunto en su página web. Sin cortes, sin roturas, sin consecuencias imprevistas y sin dolores de cabeza ... es estándar jwPlayer API y AS3 markup en uso.

Pasar el jwPlayer en sí mismo es 100% jwPlayer , mientras que está vinculado a su objeto flash indirectamente.


Según sus comentarios escritos, JW Player no tendrá acceso a JavaScript y usará Firefox Source que es un 3D Game/Chat Engine especializado sin acceso a ningún elemento DOM fuera del reproductor; la mejor solución es usar JW Player Enterprise Edition .

Esa solución lo pondrá en contacto con el departamento de Marketing e Ingeniería , que puede proporcionarle una solución integral para integrar JW Player en su propio producto.

Haga clic en la imagen a continuación que también incluye la información de Licencia :


Asumiendo que mis escenarios de prueba son representativos de sus casos de uso, creo que logré solucionar el problema.

La esencia del enfoque es reemplazar RootReference.root y RootReference.stage con un objeto de escenario falso que usted controle. Debido a que la mayoría de las clases de jwPlayer se refieren a esas variables estáticas en lugar de sus propias variables de root y stage , esto parece funcionar, en su mayor parte. Lo que terminó siendo el problema más complicado fue trabajar con los objetos Stage.stageVideo , que creo que son los objetos de video acelerados por hardware. Estos siempre están unidos al stage y, por lo tanto, no son compatibles con el objeto de escenario falso. El principal problema con estos es el posicionamiento, y lo tengo casi todo resuelto, pero todavía hay un error que describiré más adelante, pero debería estar bien, ahora.

El script de inserción de jwPlayer estaba causando muchos problemas, así que para comenzar, cambié a la incrustación normal basada en SWFObject y agregué una función de JavaScript a la página llamada getFlashvars() que devolvía la configuración. Luego, cambié el método com.longtailvideo.jwplayer.utils.Configger.loadExternal() a lo siguiente:

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) {} } }

Es algo con lo que probablemente no tenga que lidiar por no usar una página web.

La clase de etapa falsa se llama StageInterceptor y es singleton. Para aplicarlo, hubo cambios menores en la clase 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 question: http://.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 } } } } }

Además, eliminé el método de set stage() setter de la clase.

En la clase de documento, tengo el siguiente código. El manejador MouseEvent.CLICK es para probar el posicionamiento y cambiar el tamaño de la película. Lo único que realmente necesitas son las primeras líneas:

// 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; } });

Puse StageInterceptor en el paquete somePackage . Se parece a esto:

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); } } }

El problema que queda tiene que ver con el posicionamiento de las instancias de video cuando se inicializan. Creo que simplemente llama a StageInterceptor.singleton.updateStageVids(); en el punto correcto hará el truco, pero no estoy seguro. La edición a continuación explica cómo se trató esto.

No estoy seguro de qué tan bien funcionará si no está utilizando stageVideo . Pero, con un poco de suerte, esto moverá las cosas en la dirección correcta.

Editar:

StageInterceptor clase StageInterceptor para hacer un mejor trabajo escalando y posicionando el video.

Además, parece que la posición inicial de los videos (al menos cuando se trata de un stageVideo, ¿es eso lo que está usando?) Puede corregirse mediante una pequeña edición en la clase com.longtailvideo.jwplayer.media.VideoMediaProvider . Agregar import somePackage.StageInterceptor; a las declaraciones de importación en la parte superior y luego reemplazar esta línea (enlace a la fuente):

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

A:

StageInterceptor.singleton.updateStageVids();

Entonces el método se ve así:

/** 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(); } } }

Esto debería ser el truco, pero no lo he probado para videos que no sean de etapa. Y esta actualización también asume que estás reproduciendo videos progresivamente, sin usar medios RTMP.

Editar:

Para habilitar el movimiento y el cambio de tamaño del reproductor con videos que no son de StageVideo, pero que aún se cargan progresivamente, los contenidos del método com.longtailvideo.jwplayer.view.View.resizeMasker() deben ser comentados o eliminados:

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(); */ }

También quiero mencionar que la versión de código abierto de jwPlayer se rige bajo la licencia de Creative Commons, como se indica en su sitio :

JW Player 6 - Open Source Edition El uso de la edición JW Player Open Source se rige por una licencia de Creative Commons. En breve:

Fuente abierta de JW Player: puede utilizar, modificar, copiar y distribuir esta edición siempre que sea para uso no comercial, proporcione atribución y comparta bajo una licencia similar. El resumen de la licencia y el texto completo se pueden encontrar aquí: CC BY-NC-SA 3.0