services | platforms | author |
---|---|---|
media-services |
javascript |
Ian N. Bennett (ianisms) |
An Azure Media Player plugin that enables subclipping a live or on-demand video stream.
The Azure Media Player (AMP) subclipper plugin is a plugin that allows users to subclip a live or video-on-demand stream. Streams can be subclipped with frame-accuracy or group-of-photos (GOP) accuracy. The plugin outputs the mark-in and mark-out points in the stream that can then be consumed by the Azure Media Services subclipper API. The functionality and usage of the subclipper is detailed in our blog post.
A public, hosted deployment of the subclipper is available at the Azure Media Subclipper Plugin webpage.
Special thanks to Ian N. Bennett for his help and contributions to this project.
- AMVE Project - The typescript source project
- AMVESample Project - A demo site used for demonstrating the fulling minified AMVE source.
- Use Visual Studio 2015. Make sure you have NuGet package Manager set to allow downloading of missing packages.
- Build the AMVE project. After building, the project will do the necessary minification of the resultant .js and .css files and copy all of the necessary files to the AMVESample project.
The Azure Media Video Editor (AMVE) is a plugin for The Azure Media Player (AMP) and as such requires AMP to work. At the time of this release, AMVE has been tested with AMP version 1.7.4. It is quite possible that AMVE will work with later versions of AMP however, there is no guarantee.
For more information on how to add Azure Media Player to your project, please see the Azure Media Player documentation, Azure Media Player demo and Azure Media Player samples.
To use the Azure Media Video Editor(AMVE) you'll first need to add the necessary CSS and JavaScript files to your application. AMVE expects the following files to operate:
- amve.min.css
All font files must be placed in fonts directory relative to amve.min.css
- amve.eot
- amve.svg
- amve.ttf
- amve.woff
- amve.min.js
Next we'll need to add the references to the JavaScript and CSS files to your page.
Add the following JavaScript reference in your page:
<script src="amve.min.js"></script>
Add the following CSS reference to your page after the AMP CSS reference(s) like so:
<link rel="stylesheet" type="text/css" href="//amp.azure.net/libs/amp/1.7.4/skins/amp-default/azuremediaplayer.min.css" />
<link rel="stylesheet" type="text/css" href="amve.min.css" />
With the requisite references in place, we can now add the plugin registration to our AMP configuration like so:
var myOptions = {
'nativeControlsForTouch': false,
autoplay: true,
controls: true,
poster: '',
flashSS: {
swf: 'tech-wrappers/Players/osmf/StrobeMediaPlayback.2.0.swf',
plugin: 'tech-wrappers/Players/osmf/MSAdaptiveStreamingPlugin-osmf2.0.swf'
},
silverlightSS: {
xap: 'tech-wrappers/Players/smf/SmoothStreamingPlayer.xap'
},
plugins: {
AMVE: { containerId: 'amve', customMetadataContainerId: 'custommetadata', clipdataCallback: onClipdataCallback, keyboardShortcutConfig: keyboadShortcutConfig }
}
};
var myPlayer = amp('vid1', myOptions);
AMVE needs a container element to hold the editor UI DOM that wraps AMP. This element should wrap around the element used for AMP like so:
<div id="amve">
<video id="vid1" class="azuremediaplayer amp-default-skin amp-big-play-centered">
<p class="amp-no-js">To view this video please enable JavaScript, and consider upgrading to a web browser that supports HTML5 video</p>
</video>
</div>
You can add a DOM fragment containing custom UI that will be pulled into the submission dialog. To do so, add the DOM fragment as a child of the container element described in section 4. The fragment will be placed into the proper DOM hierarchy by AMVE after AMVE loads. To that end, it is best to set CSS visibility of the fragment to hidden to start. The id for the element is passed to AMVE as the customMetadataContainerId parameter which is further explained in section 8. An example of a custom submission UI dialog fragment is as follows:
<div id="amve">
<video id="vid1" class="azuremediaplayer amp-default-skin amp-big-play-centered">
<p class="amp-no-js">To view this video please enable JavaScript, and consider upgrading to a web browser that supports HTML5 video</p>
</video>
<div id="custommetadata">
<hr />
<label>Test1: </label> <input id="test1" type="text" value="Test 1" /><br>
<label>Test2: </label> <input id="test2" type="text" value="Test 2" /><br>
<label>Test3: </label> <input id="test3" type="text" value="Test 3" /><br>
<label>Test4: </label> <input id="test4" type="text" value="Test 4" />
<hr/>
<label>Color: </label><br/>
<input type="radio" name="colorchoice" value="red" checked> Red<br>
<input type="radio" name="colorchoice" value="blue"> Blue<br>
<input type="radio" name="colorchoice" value="green"> Green
<hr />
<label>Food: </label><br />
<input type="checkbox" name="foodchoices" value="breakfast"> Breakfast<br>
<input type="checkbox" name="foodchoices" value="lunch"> Lunch
</div>
</div>
Create a function with the signature onClipdataCallback(clipData) that will be called when a clip has been created. A reference to the function will be passed to AMVE as the clipDataCallback parameter described in section 8. The clipData object passed to the callback has all of the data necessary to create a clip using AMS. The properties of the clipData object are as follows:
Property | Description |
---|---|
src | The src uri of the stream being clipped. |
markIn | The time in seconds for the beginning of the clip. |
markOut | The time in seconds for the end of the clip. If the markOut is zero it is assumed that the stream should be trimmed from the start of the stream to the markIn point. |
title | A title for the clip. |
description | A Description for the clip. |
thumbnail | The base64 encoded image URI for the chosen thumbnail. |
function onClipdataCallback(clipData) {
if (clipData) {
var dataTxt = 'data.src: ' + clipData.src +
'\ndata.markin: ' + formatTime(clipData.markIn) +
'\ndata.markout: ' + formatTime(clipData.markOut) +
'\ndata.title: ' + clipData.title +
'\ndata.description: ' + clipData.description +
'\ndata.thumbnail: ' + (clipData.thumbnail ? clipData.thumbnail.dataUrl : null);
alert(dataTxt);
}
}
For AMS, you should format time per the AMS clip job specification. At the time of this documentation the following function will format time appropriately:
function formatTime(time) {
var d = Math.floor(time / 86400);
time -= (d * 86400);
var h = Math.floor(time / 3600) % 24;
time -= (h * 3600);
var m = Math.floor(time / 60) % 60;
time -= (m * 60);
var s = Math.floor(time);
time -= s;
var hs = Math.floor(time * 100);
var returnVal = '';
returnVal = returnVal + (d > 0) ? d + '.' : '';
returnVal = returnVal + (h < 10 ? ('0' + h) : ('' + h));
returnVal = returnVal + ':' + (m < 10 ? ('0' + m) : ('' + m));
returnVal = returnVal + ':' + (s < 10 ? ('0' + s) : ('' + s));
if (hs > 0) {
returnVal = returnVal + '.' + hs;
}
return returnVal;
}
AMVE has pre-configured shortcut configurations that map to Adobe Premier Pro or Avid. You can also create your own by creating an instance of AMVE.KeyboardShortcutConfig and configuring the shortcut mappings like below. The completed KeyboardShortcutConfig instance would then be passed as a parameter to AMVE as described in section 8. An example of using the Adobe Premier Pro, Avid or custom KeyboardShortcutConfig is as follows:
//Adobe Premier Pro keyboard shorcut config
var keyboadShortcutConfig = new AMVE.AdobePremierProShortcutConfig();
//Avid keyboard shorcut config
keyboadShortcutConfig = new AMVE.AvidShortcutConfig();
// Custom keyboard shorcut config
keyboadShortcutConfig = new AMVE.KeyboardShortcutConfig();
keyboadShortcutConfig.playPauseShortcut = 'space';
keyboadShortcutConfig.markInShortcut = 'i';
keyboadShortcutConfig.markOutShortcut = 'o';
keyboadShortcutConfig.goToInShortcut = 'shift+i';
keyboadShortcutConfig.goToOutShortcut = 'shift+o';
keyboadShortcutConfig.clearInShortcut = 'ctrl+shift+i';
keyboadShortcutConfig.clearOutShortcut = 'ctrl+shift+o';
keyboadShortcutConfig.clearBothShortcut = 'ctrl+shift+x';
keyboadShortcutConfig.playInToOutShortcut = 'ctrl+shift+space';
keyboadShortcutConfig.playToOutShortcut = 'ctrl+space';
keyboadShortcutConfig.ffwdShortcut = 'ctrl+right';
keyboadShortcutConfig.rwdShortcut = 'ctrl+left';
keyboadShortcutConfig.backOneFrameShortcut = 'left';
keyboadShortcutConfig.backFiveFramesShortcut = 'shift+left';
keyboadShortcutConfig.backOneSecondShortcut = 'alt+shift+left';
keyboadShortcutConfig.backOneGopShortcut = 'ctrl+shift+left';
keyboadShortcutConfig.fwdOneFrameShortcut = 'right';
keyboadShortcutConfig.fwdFiveFramesShortcut = 'shift+right';
keyboadShortcutConfig.fwdOneSecondShortcut = 'alt+shift+right';
keyboadShortcutConfig.fwdOneGopShortcut = 'ctrl+shift+right';
keyboadShortcutConfig.markInOneFrameShortcut = 'alt+,';
keyboadShortcutConfig.markInFiveFramesShortcut = 'alt+shift+,';
keyboadShortcutConfig.markOutOneFrameShortcut = 'alt+.';
keyboadShortcutConfig.markOutFiveFramesShortcut = 'alt+shift+.';
keyboadShortcutConfig.undoShortcut = 'ctrl+z';
keyboadShortcutConfig.redoShortcut = 'ctrl+y';
keyboadShortcutConfig.exportShortcut = 's';
keyboadShortcutConfig.changeModeVirtualShortcut = 'shift+v';
keyboadShortcutConfig.changeModeRenderedShortcut = 'shift+r';
keyboadShortcutConfig.changeModeTrimShortcut = 'shift+t';
There are a number of parameters that can be passed to AMVE via the plugin registration. They are all passed via the plugin options parameter in the plugin registration like so:
plugins: {
AMVE: { containerId: 'amve', customMetadataContainerId: 'custommetadata', clipdataCallback: onClipdataCallback, keyboardShortcutConfig: keyboadShortcutConfig }
}
The possible configuration parameters, some required some optional, are as follows:
Parameter | Description | Required or Optional |
---|---|---|
containerId | The id of the container element described in section 4. | Required |
customMetadataContainerId | The id for the custom submission dialog UI fragment explained in section 5. | Optional |
clipdataCallback | The callback function called upon clip submission as described in section 6. | Required |
keyboardShortcutConfig | The AMVE.KeyboardShorcutConfig instance described in section 7. | Optional |
The style of the editor, display and position of elements can be customized at will by overriding the applied CSS styles. With this said, it should be noted that manipulating the CSS properties of the editor elements could cause issues in the function of the editor.
As a guide the CSS class names and style rules generally follow the hierarchy of the components of the editor. The best way to customize the editor is by looking at the rendered and styled DOM using your favorite HTML dev tools like those built into your favorite browser.