HTML5 Video on Canvas + pixel manipulation

One of my latest experiments was to create a fullscreen background with a video, for this I used HTML5 video tag and loaded it on a canvas element.
Although it worked it somehow felt incomplete because it was simply a video as background, it needed some edge add to it, for this I decided to use Pixelate library http://close-pixelate.desandro.com/ and extend it so it supported video as well as images.
Github extension can be found also here:

https://github.com/netgfx/close-pixelate

** Note This example is best viewed with latest Chrome or Webkit browser. **

DEMO

Continue reading

Facebooktwittergoogle_pluspinterestlinkedin
linkedin

Change the event category in the GTrack OSMF plugin (dynamically)

This is somewhat a spin-off from the Media Player Anatomy series of tutorials that I’m working on, but since there is nothing to be found out there I thought to post this in case it helps anyone.
From a series of emails that I had with a representative of the RealEyes Media the only way to change the event category that is being send to the server is by changing the config.xml file.
It seemed rather insane to have a single config.xml for each category so I thought to create one on the fly as it only needs to be xml (file or build with as3 makes no difference).
FYI this is the reops tutorial on the GTrack plugin (a really nice plugin and one of the few left for free nowadays…)
GTrack Plugin Tutorial

We assume that the initial load has been done and now we want to change the category into “music”
we declare an XML template:
[cc lang=”Actionscript”]
public var xmlTemplate:XML =
UA-26485023-1
UA-24092711-1
http://www.netgfx.com/trunk/samplePlayer/sample.html








true
250
;
[/cc]

And then we change it:
[cc lang=”Actionscript”]
public function createXMLConfig(cat:String = ‘music’):XML
{
var attr:XML = new XML(xmlTemplate);

var arr:XMLList = new XMLList();
arr = attr.event;
for(var i:Number=0;i {
attr.event[i].@category = cat;
}

return attr;
}
[/cc]

This can be then loaded as follows:
[cc lang=”Actionscript”]
var customPluginConfigXML:XML = createXMLConfig();
pluginResource.addMetadataValue( “http://www.realeyes.com/osmf/plugins/tracking/google”, customPluginConfigXML );
[/cc]

At this point you might want to remove the previous MetadataValue before assigning the new one.

Enjoy!

Facebooktwittergoogle_pluspinterestlinkedin
linkedin

OSMF Strobe Media Player into Flex Mobile Project (Hero)

I have worked with Strobe media player before and it is a nice player with many features and allows a great level of customization if done properly.

So I’ll explain how to import the Strobe Media player into your Mobile Flex builder Projects successfully and create a dynamic Stream with it.

First Download Strobe Media Player: http://sourceforge.net/projects/smp.adobe/files/ (currently I work with 1.5.1)

Export the contents into a folder.

Create a new Mobile Project on Flash/Flex Builder

Copy from the Strobe Media player folder the “src/player/StrobeMediaPlayback/src” and from the same folder the “/assets” folder

Also copy from “/StrobeMediaPlayback_1.5.1-full/src/framework” the OSMF.swc

and place them on the src folder of your project. Refresh the folder tree from Flash/Flex builder.

Place the OSMF.swc into your lib folder.

Now on to some Configurations:

On the Project/Properties

On Build Path/Library Path add the assets.swc from the assets folder

On Compiler arguments add: -define CONFIG::LOGGING false -define CONFIG::FLASH_10_1 true

 

At last Coding time!

Create a new View component, open a fx:Script tag and enter the following:
[cc lang=”actionscript” width=”480″ height=”500″]
import mx.core.UIComponent;

import spark.components.Button;
import spark.components.Group;

public var $playerInstance:StrobeMediaPlayback;
var grp:Group = new Group();
protected function init(event:Event):void
{

_stage = systemManager.stage;
_stage.align = StageAlign.TOP_LEFT;
_parameters  =
{
src:”http://osmf.org/dev/videos/cathy1_SD.mp4″
, controlBarMode:”docked”
, controlBarAutoHide: true
, autoPlay: true
, playButtonOverlay:true
, showVideoInfoOverlayOnStartUp: true
};

var playerInstance:StrobeMediaPlayback = new StrobeMediaPlayback();
playerInstance.initialize(_parameters, _stage, systemManager.loaderInfo, null);
$playerInstance = playerInstance;

var ui:UIComponent = new UIComponent();
ui.addChild($playerInstance as DisplayObject);

grp.percentWidth = 100;
grp.percentHeight = 100;
addElement(grp);
grp.addElement(ui);

}

private var urlLoader:URLLoader;
private var urlRequest:URLRequest;
private var loader:Loader;
private var _stage:Stage;
private var _parameters:Object;
/* static */
private static const ALLOW_LOAD_BYTES_CODE_EXECUTION:String = “allowLoadBytesCodeExecution”;

function emptyCache()
{
$playerInstance.player.pause();
grp.removeAllElements();
this.destructionPolicy = “auto”;
}
[/cc]
Note!

Make sure to call init() on ViewActivate, or CreationComplete event. Also I recoment to assign on ViewDeactivate the emptyCache() function otherwize the sound of the video might keep on playing…

As a side note here, its better to create components in Actionscript even spark ones, than in mxml at least at this point where Flex Hero framework is still in Beta.

So thats it, now you have Strobe Media Player in your Mobile Application, especially now with 10.2 and stage video that focuses on low CPU consumption its essential for any mobile application with a video player.

!Important: In case you are not viewing a controlBar there is a chance that the default ActionBar is pushing the ControlBar downwards, so if that is the case try a different percentage for grp.percent=90, or disable the ActionBar -> set actionBarVisible = false in the View component properties.

Enjoy!

Facebooktwittergoogle_pluspinterestlinkedin
linkedin

Flex Spark VideoPlayer FullScreen bug workaround

VideoPlayer has a native bug which causes it, to loose its width and height attributes when the user cancels FullScreen mode.

A workaround is to capture the event and re-enter the player attributes as follows:

Listening to the FULL_SCREEN event at the systemManager

systemManager.stage.addEventListener(FullScreenEvent.FULL_SCREEN,funct ion(e)
{
var event = e.fullScreen;
if(event==false)
{
player.percentHeight=100;
player.percentWidth=100;
player.invalidateDisplayList();
}trace(e);
});

and if it is about to close I re-enter the percentages for the player height and width, and it again works as expected.

I hope this helps someone….

Facebooktwittergoogle_pluspinterestlinkedin
linkedin

Add Stop Button in spark VideoPlayer

I have searched all around for how to add the Stop button in a Flex spark VideoPlayer.
Here is how:

You’ll need to create two Skins one for the whole VideoPlayer where you declare the stop Button, and one more for the actual stop button

VideoPlayer Skin:

<s:SparkSkin xmlns:fx=”http://ns.adobe.com/mxml/2009″ xmlns:s=”library://ns.adobe.com/flex/spark”
xmlns:fb=”http://ns.adobe.com/flashbuilder/2009″ alpha.disabledStates=”0.5″
chromeColor.fullScreenStates=”0xCCCCCC”>
<!– A chrome color of 0xCCCCCC in the fullScreenStates means we ignore the chromeColor property
all together as 0xCCCCCC is essentially just a no-op color transform –>

<!– host component –>
<fx:Metadata>
/**
* @copy spark.skins.spark.ApplicationSkin#hostComponent
*/
[HostComponent(“spark.components.VideoPlayer”)]
</fx:Metadata>

<fx:Script fb:purpose=”styling”>
<![CDATA[
/* Define the skin elements that should not be colorized. */
static private const exclusions:Array = [“videoDisplay”, “playPauseButton”, “scrubBar”,
“currentTimeDisplay”, “timeDivider”, “durationDisplay”,
“volumeBar”, “fullScreenButton”];

/**
* @private
*/
override protected function initializationComplete():void
{
useChromeColor = true;
super.initializationComplete();
}

/**
* @private
*/
override public function get colorizeExclusions():Array
{
return exclusions;
}

/**
* @private
*/
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
dropShadow.visible = getStyle(“dropShadowVisible”);

super.updateDisplayList(unscaledWidth, unscaledHeight);
}
]]>

</fx:Script>

<!– states –>
<s:states>
<s:State name=”uninitialized” stateGroups=”uninitializedStates, normalStates” />
<s:State name=”loading” stateGroups=”loadingStates, normalStates” />
<s:State name=”ready” stateGroups=”readyStates, normalStates” />
<s:State name=”playing” stateGroups=”playingStates, normalStates” />
<s:State name=”paused” stateGroups=”pausedStates, normalStates” />
<s:State name=”stoped” stateGroups=”pausedStates, normalStates” />
<s:State name=”buffering” stateGroups=”bufferingStates, normalStates” />
<s:State name=”playbackError” stateGroups=”playbackErrorStates, normalStates” />
<s:State name=”disabled” stateGroups=”disabledStates, normalStates”/>
<s:State name=”uninitializedAndFullScreen” stateGroups=”uninitializedStates, fullScreenStates” />
<s:State name=”loadingAndFullScreen” stateGroups=”loadingStates, fullScreenStates” />
<s:State name=”readyAndFullScreen” stateGroups=”readyStates, fullScreenStates” />
<s:State name=”playingAndFullScreen” stateGroups=”playingStates, fullScreenStates” />
<s:State name=”pausedAndFullScreen” stateGroups=”pausedStates, fullScreenStates” />
<s:State name=”bufferingAndFullScreen” stateGroups=”bufferingStates, fullScreenStates” />
<s:State name=”playbackErrorAndFullScreen” stateGroups=”playbackErrorStates, fullScreenStates” />
<s:State name=”disabledAndFullScreen” stateGroups=”disabledStates, fullScreenStates”/>
</s:states>

<!– drop shadow –>
<!— @private –>
<s:RectangularDropShadow id=”dropShadow” blurX=”17″ blurY=”17″ alpha=”0.32″ distance=”4″
angle=”90″ color=”#131313″ left=”0″ top=”0″ right=”0″ bottom=”0″
excludeFrom=”fullScreenStates”/>

<!— Video and player controls are clipped if they exceed the size of the
component, but the drop shadow above is not clipped and sizes to the component.
We also set verticalScrollPosition so that when we do clip, rather than clipping
off the bottom first, we clip off the top fist. This is so the player controls
are still visible when we start clipping. –>
<s:Group id=”clippedGroup” clipAndEnableScrolling=”true” left=”0″ top=”0″ right=”0″ bottom=”0″
verticalScrollPosition=”{Math.max(0, 184-clippedGroup.height)}”>

<!– There’s a minimum size for the video and controls. If we go below that
we are clipped. –>
<s:Group minWidth=”263″ minHeight=”184″ left=”0″ right=”0″ top=”0″ bottom=”0″>

<!– background when the videoDisplay doesn’t fill its whole spot –>
<s:Rect bottom=”1″ left=”1″ right=”1″ top=”1″
bottom.fullScreenStates=”0″ left.fullScreenStates=”0″
right.fullScreenStates=”0″ top.fullScreenStates=”0″>
<s:fill>
<s:SolidColor color=”0x000000″ />
</s:fill>
</s:Rect>

<!— @copy spark.components.VideoPlayer#videoDisplay –>
<s:VideoDisplay id=”videoDisplay” bottom=”24″ left=”1″ right=”1″ top=”1″
bottom.fullScreenStates=”0″ left.fullScreenStates=”0″
right.fullScreenStates=”0″ top.fullScreenStates=”0″ />

<!– video player controls –>
<s:Group left=”0″ right=”0″ height=”24″ bottom=”0″ bottom.fullScreenStates=”150″>

<!– actual controls with a maxWidth in non-fullScreen mode –>
<!— @copy spark.components.VideoPlayer#playerControls –>
<s:Group bottom=”0″ horizontalCenter=”0″ left=”0″ right=”0″ maxWidth.fullScreenStates=”755″ id=”playerControls”>

<!— @copy spark.components.VideoPlayer#playPauseButton –>
<s:ToggleButton id=”playPauseButton” left=”0″ bottom=”0″
skinClass=”spark.skins.spark.mediaClasses.normal.PlayPauseButtonSkin”
skinClass.fullScreenStates=”spark.skins.spark.mediaClasses.fullScreen.PlayPauseButtonSkin”
layoutDirection=”ltr”
focusIn=”event.target.depth=1″ focusOut=”event.target.depth=0″ />
<s:ButtonBase id=”stopButton” left=”38″ bottom=”0″ skinClass=”stopSkin” layoutDirection=”ltr” focusIn=”event.target.depth=1″ focusOut=”event.target.depth=0″/>

<!– scrubbar + the currentTime/duration labels –>
<s:Group left=”66″ right=”75″ top=”0″ bottom=”0″>

<!– background for scrubbar + the currentTime/duration –>
<s:Rect left=”0″ right=”0″ top=”0″ bottom=”0″>
<s:fill>
<s:LinearGradient rotation=”90″>
<s:GradientEntry color=”0xFFFFFF” color.fullScreenStates=”0x585858″ alpha.fullScreenStates=”0.55″/>
<s:GradientEntry color=”0xDCDCDC” color.fullScreenStates=”0x1E1E1E” alpha.fullScreenStates=”0.55″/>
</s:LinearGradient>
</s:fill>
</s:Rect>

<!– fill highlight (exclude in fullScreen) –>
<s:Rect left=”1″ right=”1″ top=”1″ height=”11″ excludeFrom=”fullScreenStates”>
<s:fill>
<s:SolidColor color=”0xFFFFFF” alpha=”0.3″ />
</s:fill>
</s:Rect>

<!– one pixel border –>
<s:Rect left=”1″ right=”1″ top=”1″ bottom=”1″>
<s:stroke>
<s:LinearGradientStroke weight=”1″ rotation=”90″>
<s:GradientEntry color=”0xFEFEFE” color.fullScreenStates=”0xFFFFFF” alpha.fullScreenStates=”0.12″ />
<s:GradientEntry color=”0xEAEAEA” color.fullScreenStates=”0xFFFFFF” alpha.fullScreenStates=”0.09″ />
</s:LinearGradientStroke>
</s:stroke>
</s:Rect>

<!– border for the scrubbar/time label controls –>
<s:Rect left=”-1″ right=”0″ top=”0″ bottom=”0″>
<s:stroke>
<s:SolidColorStroke color=”0x131313″ color.fullScreenStates=”0x222222″ alpha.fullScreenStates=”0.66″ />
</s:stroke>
</s:Rect>

<!– scrub bar + currentTime/duration in a HorizontalLayout –>
<s:Group left=”0″ right=”0″ height=”23″ bottom=”0″>
<s:layout>
<s:HorizontalLayout verticalAlign=”middle” gap=”1″ />
</s:layout>

<!– spacer –>
<s:Rect width=”7″ height=”1″ />

<!— @copy spark.components.VideoPlayer#scrubBar –>
<s:ScrubBar id=”scrubBar” width=”100%” liveDragging=”true”
skinClass=”spark.skins.spark.mediaClasses.normal.ScrubBarSkin”
skinClass.fullScreenStates=”spark.skins.spark.mediaClasses.fullScreen.ScrubBarSkin” />

<!– spacer –>
<s:Rect width=”8″ height=”1″ />

<!— @copy spark.components.VideoPlayer#currentTimeDisplay –>
<s:Label id=”currentTimeDisplay” color.fullScreenStates=”0xFFFFFF” />

<!— @private –>
<s:Label id=”timeDivider” text=”/” color.fullScreenStates=”0xFFFFFF” />

<!— @copy spark.components.VideoPlayer#durationDisplay –>
<s:Label id=”durationDisplay” color.fullScreenStates=”0xFFFFFF” />

<!– spacer –>
<s:Rect width=”8″ height=”1″ />
</s:Group>

</s:Group>

<!— @copy spark.components.VideoPlayer#volumeBar –>
<s:VolumeBar id=”volumeBar” snapInterval=”.01″ stepSize=”.01″ liveDragging=”true”
right=”37″ bottom=”0″
layoutDirection=”ltr”
skinClass=”spark.skins.spark.mediaClasses.normal.VolumeBarSkin”
skinClass.fullScreenStates=”spark.skins.spark.mediaClasses.fullScreen.VolumeBarSkin”
focusIn=”event.target.depth=1″ focusOut=”event.target.depth=0″ />

<!— @copy spark.components.VideoPlayer#fullScreenButton –>
<s:Button id=”fullScreenButton” right=”0″ bottom=”0″ label=”Fullscreen”
skinClass=”spark.skins.spark.mediaClasses.normal.FullScreenButtonSkin”
skinClass.fullScreenStates=”spark.skins.spark.mediaClasses.fullScreen.FullScreenButtonSkin”
focusIn=”event.target.depth=1″ focusOut=”event.target.depth=0″ />

</s:Group>

</s:Group>

<!– border –>
<s:Rect left=”0″ right=”0″ top=”0″ bottom=”0″ excludeFrom=”fullScreenStates”>
<s:stroke>
<s:SolidColorStroke color=”0x131313″ />
</s:stroke>
</s:Rect>

</s:Group>
</s:Group>
</s:SparkSkin>

————————————————————————-
::: Stop Button Skin :::

<s:SparkSkin xmlns:fx=”http://ns.adobe.com/mxml/2009″ xmlns:s=”library://ns.adobe.com/flex/spark”
xmlns:fb=”http://ns.adobe.com/flashbuilder/2009″ >

<!– host component –>
<fx:Metadata>
[HostComponent(“spark.components.supportClasses.ButtonBase”)]
</fx:Metadata>

<fx:Script fb:purpose=”styling”>
/* Define the skin elements that should not be colorized. */
static private const exclusions:Array = [“stopSymbol”];

/**
* @private
*/
override public function get colorizeExclusions():Array {return exclusions;}

/* Define the symbol fill items that should be colored by the “symbolColor” style.*/
static private const symbols:Array = [“stopSymbolFill1_1”, “stopSymbolFill1_2”,
“stopSymbolFill1_3”, “stopSymbolFill1_4”, “stopSymbolFill1_5”];

/**
* @private
*/
override public function get symbolItems():Array {return symbols};

/**
* @private
*/
override protected function initializationComplete():void
{
useChromeColor = true;
super.initializationComplete();
}
</fx:Script>

<!– states –>
<s:states>
<s:State name=”up” />
<s:State name=”over” stateGroups=”overStates” />
<s:State name=”down” stateGroups=”downStates” />
<s:State name=”disabled” stateGroups=”disabledStates” />
</s:states>

<!– layer 1: fill –>
<s:Rect left=”1″ right=”1″ top=”1″ bottom=”1″>
<s:fill>
<s:LinearGradient rotation=”90″>
<s:GradientEntry color=”0xFFFFFF”
color.overStates=”0xCACACA”
color.downStates=”0xA8A8A8″ />
<s:GradientEntry color=”0xDCDCDC”
color.overStates=”0x8D8D8D”
color.downStates=”0x6B6B6B”/>
</s:LinearGradient>
</s:fill>
</s:Rect>

<!– layer 2: One pixel stroke inside border (exclude in downStates) –>
<s:Rect left=”1″ right=”1″ top=”1″ bottom=”1″ excludeFrom=”downStates”>
<s:stroke>
<s:LinearGradientStroke weight=”1″ rotation=”90″>
<s:GradientEntry color=”0xFEFEFE” alpha.overStates=”0.22″ />
<s:GradientEntry color=”0xEAEAEA” alpha.overStates=”0.22″ />
</s:LinearGradientStroke>
</s:stroke>
</s:Rect>

<!– layer 3: fill highlight (exclude in downStates) –>
<s:Rect left=”1″ right=”1″ top=”1″ height=”11″ excludeFrom=”downStates”>
<s:fill>
<s:SolidColor color=”0xFFFFFF”
alpha=”0.3″
alpha.overStates=”0.12″ />
</s:fill>
</s:Rect>

<!– layer 4: downstate inset border (include only in downStates) –>
<s:Rect left=”1″ top=”1″ right=”1″ height=”1″ includeIn=”downStates”>
<s:fill>
<s:SolidColor color=”0x000000″ alpha=”0.4″ />
</s:fill>
</s:Rect>
<s:Rect left=”1″ top=”2″ right=”1″ height=”1″ includeIn=”downStates”>
<s:fill>
<s:SolidColor color=”0x000000″ alpha=”0.12″ />
</s:fill>
</s:Rect>
<s:Rect left=”1″ top=”1″ bottom=”1″ width=”1″ includeIn=”downStates”>
<s:fill>
<s:SolidColor color=”0x000000″ alpha=”0.12″ />
</s:fill>
</s:Rect>
<s:Rect right=”1″ top=”1″ bottom=”1″ width=”1″ includeIn=”downStates”>
<s:fill>
<s:SolidColor color=”0x000000″ alpha=”0.12″ />
</s:fill>
</s:Rect>

<!– layer 5: border – put on top of the fill so it doesn’t disappear when scale is less than 1 –>
<s:Rect left=”0″ right=”0″ top=”0″ bottom=”0″ width=”28″ height=”24″>
<s:stroke>
<s:SolidColorStroke color=”0x131313″ />
</s:stroke>
</s:Rect>

<!— Defines the Stop symbol. –>
<s:Group horizontalCenter=”0″ verticalCenter=”0″ id=”stopSymbol”>

<!– triangle –>
<s:Rect left=”0″ top=”0″ height=”11″ width=”10″>
<s:fill>
<s:LinearGradient rotation=”90″>
<!— @private –>
<s:GradientEntry color=”0x252525″ alpha=”0.75″ ratio=”0.1″ id=”stopSymbolFill1_1″/>
<!— @private –>
<s:GradientEntry color=”0x404040″ alpha=”0.75″ ratio=”0.2″ id=”stopSymbolFill1_2″/>
<!— @private –>
<s:GradientEntry color=”0x4B4B4B” alpha=”0.75″ ratio=”0.55″ id=”stopSymbolFill1_3″/>
<!— @private –>
<s:GradientEntry color=”0x424242″ alpha=”0.75″ ratio=”0.9″ id=”stopSymbolFill1_4″/>
<!— @private –>
<s:GradientEntry color=”0xC4C4C4″ alpha=”0.75″ ratio=”1.0″ id=”stopSymbolFill1_5″/>
</s:LinearGradient>
</s:fill>
</s:Rect>
</s:Group>

</s:SparkSkin>

————————————————————-
::: SAMPLE Video Player :::

<s:VideoPlayer
source=”{customURL2}”
width=”100%” height=”100%”
loop=”true” skinClass=”VCPlayer”
complete=”vpCompleteHandler(event);”
mediaPlayerStateChange=”vpMediaPlayerStateChangeHandler(event);” autoPlay=”true” autoRewind=”true” id=”flayer” pauseWhenHidden=”true” dropShadowVisible=”false”/>

Facebooktwittergoogle_pluspinterestlinkedin
linkedin