Video Screen Snapshot Make video screen snapshots directly within JWPlayer 7



This demonstrates manually capturing a video frame to a jpeg image and saving to a backend service.

Introduction

This demonstrates manually capturing a video frame to a jpeg or png image and saving to a backend service either as file uploads or base64 encoded images.

The `dimensions` config can produce multiple sizes including thumbnails. Browsers do not do a good job resizing so a new system has been implemented to provide higher quality downsizing and resampling that should match Photoshop. Web Workers is used for fast processing and non blocking. Web Workers is available in most modern browsers including on Windows 7. A WebGL option for faster resizing will be made available.

For browsers that don't support Html Blob and Canvas include the Html5 polyfills to allow for capture support.

A Flash work around solution is provided for RTMP and HLS streams. The Flash solution now uses new fast graphics functions in Flash that also works around security contraints with both RTMP and HLS capturing.

Work around solution for non-inline player support like on Iphone.

Example backends provided have been upgraded to provide both multiple file upload support and saving directly to Amazon S3.

Html5 Features

  • Capture of video frame from any http streaming source with Cross Origin Resource Sharing enabled and a browser that supports the canvas element, a fallback for IE is supplied.
  • Jpeg and PNG encoding on the fly with a quality setting for jpeg encoding.
  • High quality and fast browser based resizing solution that can provide multiple sizes including thumbnails.
  • Javascript api service to automate the capture.
  • Returning the canvas to display in a preview window.
  • Example backend included to demonstrate saving the image sent as multiple image uploads of as base64 encoded images.
  • Example backend included to demonstrate generating an authentication signature and post data options for uploading files directly to S3.
  • Csrf token security support for authentating the upload service.
  • Includes a Notification plugin to display user feedback.
  • Now works with Cloudfront video. Cloudfront now supports the OPTIONS request method which is sent via the browser to validate the cross origin request. see http://docs.amazonwebservices.com/AmazonS3/latest/dev/cors.html.
  • Cors support for browsers lacking crossOrigin video tag specs like Safari and IE11 using a proxy player work around solution.
  • Local downloads support for Chrome and Firefox. Safari lacks special file download features and therefore requires to be opened in a new tab.
  • Support and tested in Chrome,Firefox,Safari, IE 11, Edge Browser, IOS, Android. (Safari and IE11 both need the CORS proxy). Possibly support for IE9-IE10 with canvas and blob support fallbacks included.
  • Playlist configuration support.
  • Work around solution for non-inline player support like on Iphone. A notification will be provided when exiting fullscreen to start the capture at that current time.

Flash fallback Features

  • Direct capture and doesn't require custom stream providers anymore apart from HLS which is handled internally.
  • Capture of video frame from any http or rtmp streaming source with StreamVideoSampleAccess enabled.
  • Support for Adobe HTTP Streaming is now possible due to some security sandbox workarounds.
  • Capture support for Flash Vimeo based streams is possible although Youtube and Dailymotion have restrictive policies so will not work.
  • Jpeg and PNG encoding on the fly with a quality setting for jpeg encoding.
  • Javascript api service to automate the capture.
  • Returning base64 encoded image to preview in html via the Javascript api.
  • Example backend included to demonstrate saving the image sent.
  • Csrf token security support.
  • Local client download support.
  • Resize scaling feature for larger videos.
  • Thumbnail creation support.
  • Thumbnails only option to prevent encoding the larger frame and only the thumbnail frame for faster realtime captures.
  • Support for Stage Video enabled streaming with some work arounds for Safari and Firefox.
  • Support HLS and Adobe HTTP Streaming streaming with some work arounds for security sandbox constraints.
  • Support for Flash HLS Streaming with the use of a built in playback feature to work around Flash sandbox security contraints and JWPlayer api design flaws which prevents the ability to access it's stream and video for switching out of stage video etc. This requires reloading the stream and seeking to the current time before capture therefore a tiny delay beforehand. For live streams the seeking may not be frame accurate due to the work around requirements but a tiny backwards cache is enabled to allow for it. With multi bitrate streams the largest bitrate manifest will be used for capture.
  • Support for RTMP, HLS and HDS live streaming capture.
  • Flash proxy player for capture work around for RTMP and HLS streams using fast native graphics capture functions in Flash Player 11.6.

Html5 Known Issues

  • Only works for now in Chrome and Firefox browsers. Safari / Webkit / IE 11 will work with same origin videos, it does not have support for cross origin with the video tag therefore the canvas cannot obtain the image. A proxy work around is required to make it function. see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#attr-media-crossorigin.
  • The video server backend requires to have Cors support enabled with the Access-Control-Allow-Origin header.
  • Does not work with Cloudfront video yet as Cloudfront does not support the OPTIONS request method which is sent via the browser to validate the cross origin request therefore returns errors and the video does not load. S3 has support for Cors rules see http://docs.amazonwebservices.com/AmazonS3/latest/dev/cors.html.
  • Considered a very experimental feature until Cors / Canvas / Html5 video is standardised.
  • Local file downloads support is considered experimental until all browsers support file download attributes.
  • Safari has problems with local save api's and will attempt to launch a new tab to be manually saved via command-s, it also can not handle mimetypes delivered to it, this is due to standards issues with the html5 api functions. Firefox,IE 11 all bring up file dialogs and Chrome will download automatically with no file dialog being able to be forced. File saving in html5 is considered experimental due to all these inconsistencies.
  • Does not work with Html5 api players like Youtube/Vimeo due to cross origin security constraints.

Flash Known Issues

  • JWPlayer 7 Flash is targeted to Flash 11.1. This means the Flash snapshot plugin cannot use faster native capture and image encoding features available in Flash 11.6.
  • Because of the JWplayer version targeting HLS Flash is not possible until a proxy capture player is available due to Flash security work arounds are not working for HLS.
  • RTMP streams require the StreamVideoSampleAccess or VideoSampleAccess enabled to be able to capture the video data in Wowza and Flash Media Server. See http://livedocs.adobe.com/flashmediaserver/3.0/docs/help.html?content=08_xmlref_168.html and http://www.wowza.com/resources/WowzaMediaServer_ConfigurationReference.pdf.
  • Both HDDN and Cloudfront RTMP do not have these video sample data access settings enabled unfortunately so only Http progressive download will work with these CDN's.
  • Hddn's Flash crossdomain master policy file is empty therefore data access to the http streams are not possible for now due to Flash crossdomain sandbox issues and the requirement of a root policy file.
  • As above requires a crossdomain.xml policy file configured on the server for http based streams for this feature to work correctly.
  • CDN's such as S3 which implement 302 redirection cause issues with the stream obtaining the crossdomain policy file in the background a fallback system is in place to obtain the policy file from the domain of the requested video instead.
  • For local client download support any files from Cloudfront which has redirections which requires reloading of security policies, user interaction is required to initiate the download after capture. A notification is provided to notify this. Due to flaws with the JWPlayer API a delay is required when capturing stage video content which is enabled by default. User interaction therefore is also required.
  • In Stage Video streaming mode the stream requires to switch to normal video display for capture. Workarounds are required for bugs in Safari and Firefox on OSX when switching back after capture.
  • For RTMP live streaming and Stage Video mode which is enabled in JWPlayer by default, the stream requires to restart after capture to workaround a Firefox and Safari bug.
  • A work around is required for HLS and HDS streaming due to Flash security sandbox contrains and the type of streaming does not rely on cross domain policies. This prevents capture therefore modifications have been made to the plugins to accomodate this feature.
  • The JWPlayer HLS Edition feature is closed sourced and the player Flash Api is severely limited and flawed so the plugin is unable to obtain it's stream for providing the sandbox security work around and switching out of stage video. An alternative work around for capturing is required. This requires reloading the stream and seeking to the current position before capture and incurs a delay. The seeking to bring up the required position may not be frame accurate for live streams.
  • Does not work with Youtube or any other API player streams due to Flash sandbox security issues. New developments in Flash 11.6 work around these issues and such feature might be available soon.
  • JWPlayer 7 has completely disabled uneccesarily StageVideo GPU playback acceleration from their streaming providers due to the fact Flash is now handled with Html overlays. Due to this, custom stream providers are not required anymore to handle the capture and the video display can be obtained from the display list instead directly. All StageVideo capture work arounds have now been disabled.
  • Local file saving in Flash requires to be handled by Javascript and Html5 processing due Html controls preventing access to user clicks required for security reasons. These features have now been disabled in Flash.

Demo

Contact for a site or local demo download.

(Current Version 4.2.0)

Compatibility

  • JWPlayer 7.0 and above

Plugin Available For Purchase via Paypal


License Options
Domain(s)

(Version 4.2.0)

License Information

The Controlbar Video Snapshot plugin is a once off commercial license with updates and support to the Video Snapshot plugin only. Flowplayer related questions and support may be provided on their forums at http://flash.flowplayer.org/forum/index.html

  • Single Domain License - Suitable for small sites with updates and unlimited support included.
  • Multi Domain License - Suitable for larger sites and video platform sites with updates, feature requests and unlimited priority support included.
  • Bundle License - Provide both JWPlayer 6 Flash features with Html5 alternative.

Note:

With your purchase please provide your domains to be provided with your licensed plugin. New domains need to be requested manually for the moment.

Refund Policy:

Please try the demo before purchase or request for a 60 day site demo. Refunds will not be issued unless under some circumstances sorry for the inconvenience.

Configuration

Here is a list of the configuration options:

property / datatype default description
savelocal
boolean
false Enable local download support. No server side is required.
captureswf
string
false The capture proxy player for Flash HLS based streams.
originbaseurl
string
For cross origin work arounds, use this base url to a proxy location on the same domain as the page.
serverurl
string
The location to the backend server for saving the images.
tokenurl
string
The location of the backend server for obtaining a csrf token.
token
string
The csrf token to use with the save request.
tokendata
object
Configure specific data to use for sending to the token server request. The server can use this for extra authentication.
s3url
string
The url to the S3 bucket ie //bucket.s3-region.amazonaws.com",
signatureurl
string
The location of the backend server for obtaining the generated authentication signature for s3 requests.
s3
object
The generated s3 signature provided by the backend configured directly on the player.
postfiles
boolean
false Unless there is three or more dimensions configured. Set postfiles to upload images as files. With the S3 backend multiple image uploads is sent as default and a requirement.
type
string
png The image type to use for encoding either png or jpeg.
quality
string
1 The png / jpeg compression quality.
dimensions
array
A list of dimensions to use for resizing the still including to thumbnails. For thumbnails the `thumbnail` property is required.
unsharpAmount
number
80 The sharpness setting for the image resizer in percentage. 50-100 is a good range.
unsharpRadius
number
0.6 Radius of Gaussian blur for the image resizer that affects sharpness. values between 0.5 and 2.0
unsharpThreshold
number
2 Threshold for unsharp mask for the image resizer. values between 0 and 255.
debug
boolean
false Display debug logs.
captureswf
string
The location to the Flash proxy player for capturing.
pauseOnCapture
boolean
true Pause the stream on capture.
notify
boolean
true Display notifications.
notifications
object
The config for the notifications display.
previewClass
string
For the html5 plugin, the previewClass to use for the image preview display. For the flash plugin, the previewClass to use for the image preview display and is obtained within the capture completion callback.
thumbPreviewClass
string
For the html5 plugin, the thumbPreviewClass to use for the thumbnail preview display. For the flash plugin, the thumbPreviewClass to use for the thumbnail preview display and is obtained within the capture completion callback.

Notifications

The notifications config enables to style and configure the notifications message dialog.

property / datatype required description
saveready
string
Click Capture Again To Save When the capture is ready to be saved locally. Html5 and Safari only.
processing
string
Processing Please Wait The processing message.
error
string
Capture Failed Try Again The capture failure message.
complete
string
Capture Completed The capture complete message.
noinline
string
Click Capture To Take Snapshot At The Current Time For non-inline players like on Iphone this will notify the user to start capturing after exiting native player fullscreen.

Notifications Styling

The following css classes are used by styling :

stylename example description
notification .notification { width: 300px; height: 50px; text-align: center; vertical-align: middle; background-color: #CCCCCC; border-radius: 10px; margin-left: auto ; margin-right: auto ; } The Notification plugin style.
notification.message .notification.message { color: #FFFFFF; font-size: 12px; } The notification message text styling.
snapshot.preview .snapshot.preview { float: right; width: 600px; } The snapshot preview display style.

Filename Configuration

To send a custom filename for the capture image configure this on the video config with a `snapshotnames` or `snapshotname` property with a time postfix format to add the current frame time

When using a multiple dimensions config the filenames list needs to match and the `snapshotnames` is required.


    snapshotname: "test2-[time]"

    snapshotnames: [
    "test2.jpg",
    "test2-thumb.jpg"
    ],

Multiple Dimensions

To produce multiple sizes with high quality resizing and downsampling the `dimensions` config is required. For thumnails the `thumbnail` property is required on that size.

If only a thumbnail dimension is configured the original video dimensions will be used for the larger still.

A width an height can be set. If only a width is set the height will be scaled which is the default option.


    dimensions: [
    //configure thumbnail width to auto scale height to
    { width: 180, thumbnail: true }
    ],

    dimensions: [
    { width: 600 },
    { width: 400 },
    { width: 180, thumbnail: true }
    ],

JavaScript API

Methods

The api methods are exposed on the Flowplayer 6 api.


    player.capture();
method returns description
capture Manually initiate the capture process.

Events

The capture complete event returns data for the generated encoded still and thumbnail as a base64 data uri string. For Html5 captures it also returns the original canvas. For backend storing of captures the data from the server is also returned.



    player.on("capturecomplete", function(data) {
    //data.image - the image data uri
    //data.img - the data uri as an image.
    //data.thumbnail - the thumbnail data uri
    //data.thumbnailImg = the thumbnail data uri as an image.
    //data.images - the list of resized images or original still.
    //data.data - the data returned from the backend server

    //console.log("Capture Complete: ", data);
    }).on("captureerror", function(error) {
    console.log("Capture Error: ", error);
    }).on("uploaderror", function(error) {
    console.log("Upload Error: ", error);
    }).on("uploadprogress", function(progress) {
    console.log("Uploading Progress " + (progress.loaded / progress.total * 100) + "%");
    }).on("resizeprogress", function(progress) {
    console.log("Resize Progress: " + progress.index / progress.total * 100 + "%");
    console.log("Current Size", progress.current);
    }).on("proxyprocessing", function() {
    console.log("Cors Proxy Processing");
    });

Event When does it fire?
capturecomplete(data) Html5 and Flash Version. Fired on a capture completion status and the image has been saved successfully onto the backend server. The image argument contains the generated canvas with the `canvas` property and the base64 encoded image is sent to the callback event with the `image` property to be used for displaying a preview image in the html. The data argument contains the data returned from the backend server.
captureerror(error) Returns when there is a problem making a capture.
uploaderror(error) Returns when there is a problem uploading to the backend server or Amazon S3.
uploadprogress(progress) Image uploading progress event.
resizeprogress(progress) The progress of the image resizing function.
proxyprocessing() Notification when the CORS proxy player is loading files and seeking.

Token Server

The configured token server must return a Access-Control-Allow-Origin for Ajax requests and a csrf hash in a json object string like so:


    {"token":"f38c9bd8483916513f057a6ea71a6d24"}

If extra authentication data is required along with the token hash these can be returned with the token service and sent to the image upload service.


    {"token":"f38c9bd8483916513f057a6ea71a6d24", "extrahash" : "54353985398235985328953358"}

If required the `tokendata` can be configured with extra authentication properties for the token server to use to authenticate the client and request.

NOTE: Safari tries to block third party cookie sessions with ajax requests so a special P3P header is required to work around this.

Backend Server

Included is a backend server which demonstrates handling the cors headers required for Ajax requests, filtering the post and the image sent as a base64 encoded string or as multiple file uploads. The server should provide the parameter and token hash security and base64 decode the image as a string and store on the server. File uploads should be validated. The following properties are required or optional:

property / datatype required description
image
string
The image stored as a base64 encoded string.
thumbnail
string
The thumbnail image stored as a base64 encoded string when available.
type
string
true The image type chosen either jpg or png.
token
string
false The csrf token to use with the save request, if a token is configured this can be used to check the request.
name
string
false The name of the image to use when saving.
thumbnailname
string
false The name of the thumbnail image to use when saving.
file1..3
string
false The name of the multiple file uploads post data stored as files. The file uploads are required to be validated with multiple options for security purposes.

CORS Rules Requirements

For this feature to work successfully both the backend server and the video hosting server require Cross Origin Resource Sharing rules to be enabled in the headers of the request.
This is required to enable cross origin Ajax requests when posting the captured image data and to be able to gain access to the video data within a Html5 video tag.

The header of the cors request must expose a `Access-Control-Allow-Origin` header with either a multiple list of domains including ports if using ports or an asterix wildcard to allow all domains.
A `Access-Control-Allow-Methods` can be exposed to control what request methods are allowed. For authenticated logins with cookies the `Access-Control-Allow-Credentials` header must be enabled and the feature will pass cookie sessions and other cookies along with the request.

An example request header can look like the following:


    Access-Control-Allow-Origin: http://localhost:8000
    Access-Control-Allow-Methods: GET
    Access-Control-Allow-Headers: Content-Type, Accept
    Access-Control-Allow-Credentials: true
    Content-Type: application/json

Enabling CORS on S3

Follow the guide here to enable CORS rules on the bucket.

In the required bucket, choose "Properties", then "Permissions", then choose "Edit Cors Configuration"

A configuration should look like this or a more restricted Origin with a host domain


    <?xml version="1.0" encoding="UTF-8"?>
    <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>HEAD</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <ExposeHeader>Content-Length</ExposeHeader>
    <ExposeHeader>Accept-Ranges</ExposeHeader>
    <AllowedHeader>*</AllowedHeader>
    </CORSRule>
    </CORSConfiguration>

CORS Requirements For Cloudfront

Cloudfront now supports CORS and delivers OPTIONS requests.

To enable OPTIONS support in Cloudfront goto the "Edit Behaviour" section of the Cloudfront distribution. choose Edit on the selected behaviour. Make sure in "Allow HTTP Methods" it looks like "GET, HEAD, OPTIONS". Check "OPTIONS" in the "Cached HTTP Methods" section and add all the suggested Whitelist Headers selection.

CORS Proxy

A CORS proxy is required to work around limitations with cross origin support on the video tag like with IE and Safari.

Using either Apache or Nginx server configs assuming the proxy module is enabled can be achieved like so:

Apache:


    ProxyPass /video/ //videos.electroteque.org/
    ProxyPassReverse /video/ //videos.electroteque.org/

Nginx:


    location /video/ {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-NginX-Proxy true;
    proxy_pass //videos.electroteque.org/;
    proxy_redirect off;
    }

Which translates to:


    http://origin.electroteque.org/video/big_buck_bunny_480p_h264.mp4

Testing CORS Server Requests

CORS server requests can be initiated with the following curl command:


    curl -I -H "Origin: http://localhost:8000" http://path/to/server

The CORS header should look like the following:


    Access-Control-Allow-Origin: http://localhost:8000
    Access-Control-Allow-Methods: GET, HEAD
    Access-Control-Max-Age: 3000
    Access-Control-Allow-Credentials: true
    Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method

Rtmp Server Access

Rtmp servers like FMS, Wowza and Red5 require config changes to enable access to video sample data.

Flash Media Server

Locate the `Application.xml` file within the configuration directory and edit the xml config `VideoSampleAccess` to locations of paths in the content directory like so:


<VideoSampleAccess enabled="true">low_quality;high_quality</VideoSampleAccess>

Wowza

Locate the `Application.xml` file within the application configuration directory and edit the xml config `StreamVideoSampleAccess` with an asterix `*` to enable access to all files.


<Client>
			<IdleFrequency>-1</IdleFrequency>
			<Access>
				<StreamReadAccess>*</StreamReadAccess>
				<StreamWriteAccess>*</StreamWriteAccess>
				<StreamAudioSampleAccess>*</StreamAudioSampleAccess>
				<StreamVideoSampleAccess>*</StreamVideoSampleAccess>
				<SharedObjectReadAccess>*</SharedObjectReadAccess>
				<SharedObjectWriteAccess>*</SharedObjectWriteAccess>
			</Access>
</Client>

Red5

In the application WEB-INF path locate the file `red5-web.xml` and add bean properties like so :


<bean id="rtmpSampleAccess" class="org.red5.server.stream.RtmpSampleAccess">
<property name="audioAllowed" value="true"/>
<property name="videoAllowed" value="true"/>
</bean>

Examples

Basic example.

Flowplayer configuration




    (function(jwplayer) {

    var player = jwplayer("player").setup({
    flashplayer: "jwplayer.flash.swf",
    width: 660,
    height: 350,
    debug: true,
    playlist: [
    {
    "snapshotname" : "test.png",

    sources: [
    { type: "webm", file: "//videos.electroteque.org/bitrate/big_buck_bunny_2000k.webm"},
    { type: "mp4", file: "//videos.electroteque.org/bitrate/big_buck_bunny_2000k.mp4"},
    { type: "ogg", file: "//videos.electroteque.org/bitrate/big_buck_bunny_2000k.ogv"},
    { type: "rtmp", file: "mp4:bitrate/big_buck_bunny_2000k.mp4"}
    ]
    }
    ],
    plugins: {
    "https://static.electroteque.org/js/jw7/snapshot-4.2.0.js": {
    serverurl: "https://flowplayer.electroteque.org/snapshot/index/save",
    tokenurl: "https://flowplayer.electroteque.org/snapshot/index/token",
    type: "png",
    captureswf: "VideoSnapshotPlayer-4.2.0.swf",
    dockButtonUrl: "images/snapshoticon.png",
    previewClass: "snapshot preview",
    //html5 only
    originbaseurl: "http://crossorigin.electroteque.org/video/"
    }
    }
    });


    player.on("ready",function() {
    player.on("capturecomplete", function(data) {
    console.log("Capture Complete ");
    //console.log("Capture Complete: ", data);
    }).on("captureerror", function(error) {
    console.log("Capture Error: ", error);
    }).on("uploaderror", function(error) {
    console.log("Upload Error: ", error);
    }).on("uploadprogress", function(progress) {
    console.log("Uploading Progress " + (progress.loaded / progress.total * 100) + "%");
    }).on("resizeprogress", function(progress) {
    console.log("Resize Progress: " + progress.index / progress.total * 100 + "%");
    console.log("Current Size", progress.current);
    }).on("proxyprocessing", function() {
    console.log("Cors Proxy Processing");
    });

    });



    })(window.jwplayer)



Local Download Example

This example demonstrates locally saving the generated snapshot image.

To enable the locally downloading of snapshot images configure the `saveLocal` config therefore a backend server is not required.




    (function(jwplayer) {

    var localplayer = jwplayer("local").setup({
    flashplayer: "jwplayer.flash.swf",
    width: 660,
    height: 350,
    primary: "flash",
    debug: true,

    playlist: [
    {
    "snapshotname" : "test.jpg",
    sources: [
    { type: "webm", file: "//videos.electroteque.org/bitrate/big_buck_bunny_2000k.webm"},
    { type: "mp4", file: "//videos.electroteque.org/bitrate/big_buck_bunny_2000k.mp4"},
    { type: "ogg", file: "//videos.electroteque.org/bitrate/big_buck_bunny_2000k.ogv"},
    { type: "rtmp", file: "mp4:bitrate/big_buck_bunny_2000k.mp4"}
    ],
    streamer: "rtmp://rtmp.electroteque.org/cfx/st"
    }
    ],
    plugins: {
    "https://static.electroteque.org/js/jw7/snapshot-4.2.0.js": {
    savelocal: true,
    type: "jpg",
    quality: 0.8,
    dockButtonUrl: "images/snapshoticon.png",
    previewClass: "snapshot localpreview",
    //html5 only
    originbaseurl: "http://crossorigin.electroteque.org/video/"
    }
    }
    });


    localplayer.on("ready",function() {

    localplayer.on("capturecomplete",function(data) {

    console.log("Capture Complete");
    //console.log("Image", data.image);
    //console.log("Server Returned With Data: ", data.data);

    });

    });



    })(window.jwplayer);

Thumbnails Generator Example

This example demonstrates generated an image capture and a thumbnail capture.

To enable the thumbnail capture configure the 'dimensons` config with a `thumbnail` size property.




    (function(jwplayer) {

    var thumbplayer = jwplayer("thumbnails").setup({
    flashplayer: "jwplayer.flash.swf",
    width: 660,
    height: 350,
    primary: "flash",
    debug: true,

    playlist: [
    {
    "snapshotnames": [
    "test2.jpg",
    "test2-thumb.jpg"

    ],
    sources: [
    { type: "webm", file: "//videos.electroteque.org/bitrate/big_buck_bunny_2000k.webm"},
    { type: "mp4", file: "//videos.electroteque.org/bitrate/big_buck_bunny_2000k.mp4"},
    { type: "ogg", file: "//videos.electroteque.org/bitrate/big_buck_bunny_2000k.ogv"},
    { type: "rtmp", file: "mp4:bitrate/big_buck_bunny_2000k.mp4"}
    ],
    streamer: "rtmp://rtmp.electroteque.org/cfx/st"
    }
    ],
    plugins: {
    "https://static.electroteque.org/js/jw7/snapshot-4.2.0.js": {
    serverurl: "https://flowplayer.electroteque.org/snapshot/index/save",
    tokenurl: "https://flowplayer.electroteque.org/snapshot/index/token",
    type: "jpg",
    dockButtonUrl: "images/snapshoticon.png",
    previewClass: "snapshot thumbpreview",
    thumbPreviewClass: "snapshot thumbspreview",
    dimensions: [
    //configure thumbnail width to auto scale height to
    { width: 180, thumbnail: true }
    ],
    //html5 only
    originbaseurl: "http://crossorigin.electroteque.org/video/"
    }
    }
    });


    thumbplayer.on("ready",function() {

    thumbplayer.on("capturecomplete",function(data) {

    console.log("Capture Complete");
    // console.log("Image", data.image);
    //console.log("Thumbnail", data.thumbnail);
    //console.log("Server Returned With Data: ", data.data);

    });

    });



    })(window.jwplayer);

Mutliple Sizes Example

This example demonstrates resizing multiple images including thumbnails with the high quality image resizer.

To enable resizing configure the `dimensions` config with multiple width sizes.



    (function(jwplayer) {

    var sizesplayer = jwplayer("sizes").setup({
    flashplayer: "jwplayer.flash.swf",
    width: 660,
    height: 350,
    debug: true,

    playlist: [
    {
    "snapshotnames": [
    "test2.jpg",
    "test2-thumb.jpg"

    ],
    sources: [
    { type: "webm", file: "//videos.electroteque.org/bitrate/big_buck_bunny_2000k.webm"},
    { type: "mp4", file: "//videos.electroteque.org/bitrate/big_buck_bunny_2000k.mp4"},
    { type: "ogg", file: "//videos.electroteque.org/bitrate/big_buck_bunny_2000k.ogv"},
    { type: "rtmp", file: "mp4:bitrate/big_buck_bunny_2000k.mp4"}
    ],
    streamer: "rtmp://rtmp.electroteque.org/cfx/st"
    }
    ],
    plugins: {
    "https://static.electroteque.org/js/jw7/snapshot-4.2.0.js": {
    serverurl: "https://flowplayer.electroteque.org/snapshot/index/savefiles",
    tokenurl: "https://flowplayer.electroteque.org/snapshot/index/token",
    type: "jpeg",
    quality: 0.8,
    //multiple dimensions
    dimensions: [
    { width: 600 },
    { width: 180, thumbnail: true }
    ],
    //post as multiple file uploads
    postfiles: true,
    dockButtonUrl: "images/snapshoticon.png",
    previewClass: "snapshot size1",
    thumbPreviewClass: "snapshot size2",
    dimensions: [
    //configure thumbnail width to auto scale height to
    { width: 180, thumbnail: true }
    ],
    //html5 only
    originbaseurl: "http://crossorigin.electroteque.org/video/"
    }
    }
    });


    sizesplayer.on("ready",function() {

    sizesplayer.on("capturecomplete",function(data) {

    console.log("Capture Complete");
    // console.log("Image", data.image);
    //console.log("Thumbnail", data.thumbnail);
    //console.log("Server Returned With Data: ", data.data);

    });

    });



    })(window.jwplayer);

JS API Example

This example demonstrates using the javascript api to create the capture and a javascript event to manage the capture completion. The base64 encoded image is sent to the completion callback event to be used for displaying the preview image in the html. The dock button is also configured to be disabled.





(function(jwplayer) {

    var jsapi = jwplayer("jsapi").setup({
            flashplayer: "jwplayer.flash.swf",
            width: 660,
            height: 350,
            primary: "flash",
            debug: true,

            playlist: [
              {
                "snapshot.name" : "test",
                sources: [
                                                        { type: "webm", file: "//videos.electroteque.org/bitrate/big_buck_bunny_2000k.webm"},
                                                        { type: "mp4", file: "//videos.electroteque.org/bitrate/big_buck_bunny_2000k.mp4"},
                                                        { type: "ogg", file: "//videos.electroteque.org/bitrate/big_buck_bunny_2000k.ogv"},
                                                        { type: "rtmp", file: "mp4:bitrate/big_buck_bunny_2000k.mp4"}
                 ],
                 streamer: "rtmp://rtmp.electroteque.org/cfx/st"
              }
            ],
            plugins: {
                "https://static.electroteque.org/js/jw7/snapshot-4.2.0.js": {
                    serverurl: "https://flowplayer.electroteque.org/snapshot/index/save",
                    tokenurl: "https://flowplayer.electroteque.org/snapshot/index/token",
                    type: "jpg",
                    dockButton: false,
                    previewClass: "snapshot apipreview",
                    //html5 only
                    originbaseurl: "http://crossorigin.electroteque.org/video/"
                }
            }
    });


        jsapi.on("ready",function() {

            jsapi.on("capturecomplete",function(data) {

                console.log("Capture Complete");
                console.log("Image", data.image);
                console.log("Server Returned With Data: ", data.data);

            });

        });





})(window.jwplayer);

function docapture() {
    var jsapi = jwplayer("jsapi");
    jsapi.trigger("capture");
}

Amazon S3 Client Side Upload Example

Included is a demo php script to upload the image captures directly to Amazon S3 as a backend service option.

The backend service is required to generate the V4 Amazon authentication signatures and policy to send with the post upload request.

When multiple image dimensions are configured it is required to upload each one sequentially. If filenames have paths in them the images will be uploaded to these paths.

The specific required post data with the generated policy and signatures for V4 requests. This is either returned from the signature service or configured on the player with the `s3` config.

    {
    "Content-Type":"image\/jpeg",
    "acl":"public-read",
    "success_action_status":"201",
    "policy":"generated policy",
    "X-amz-credential":"accesskey\/timestamp\/region\/s3\/aws4_request",
    "X-amz-algorithm":"AWS4-HMAC-SHA256",
    "X-amz-date":"20160629T081455Z",
    "X-amz-signature":"generatedsignature",
    "key":"${filename}"
    }


    (function(jwplayer) {

    var sizesplayer = jwplayer("sizes").setup({
    flashplayer: "jwplayer.flash.swf",
    width: 660,
    height: 350,
    debug: true,

    playlist: [
    {
    "snapshotnames": [
    "test2.jpg",
    "test2-thumb.jpg"

    ],
    sources: [
    { type: "webm", file: "//videos.electroteque.org/bitrate/big_buck_bunny_2000k.webm"},
    { type: "mp4", file: "//videos.electroteque.org/bitrate/big_buck_bunny_2000k.mp4"},
    { type: "ogg", file: "//videos.electroteque.org/bitrate/big_buck_bunny_2000k.ogv"},
    { type: "rtmp", file: "mp4:bitrate/big_buck_bunny_2000k.mp4"}
    ],
    streamer: "rtmp://rtmp.electroteque.org/cfx/st"
    }
    ],
    plugins: {
    "https://static.electroteque.org/js/jw7/snapshot-4.2.0.js": {
    s3url: "//bucket.s3-region.amazonaws.com",
    signatureurl: "http://s3upload.electroteque.org/signature",
    type: "jpeg",
    quality: 0.8,
    //multiple dimensions
    dimensions: [
    { width: 600 },
    { width: 180, thumbnail: true }
    ],
    //post as multiple file uploads
    postfiles: true,
    dockButtonUrl: "images/snapshoticon.png",
    previewClass: "snapshot size1",
    thumbPreviewClass: "snapshot size2",
    dimensions: [
    //configure thumbnail width to auto scale height to
    { width: 180, thumbnail: true }
    ],
    //html5 only
    originbaseurl: "http://crossorigin.electroteque.org/video/"
    }
    }
    });

    });



    (function(jwplayer) {

    var sizesplayer = jwplayer("sizes").setup({
    flashplayer: "jwplayer.flash.swf",
    width: 660,
    height: 350,
    debug: true,

    playlist: [
    {
    "snapshotnames": [
    "test2.jpg",
    "test2-thumb.jpg"

    ],
    sources: [
    { type: "webm", file: "//videos.electroteque.org/bitrate/big_buck_bunny_2000k.webm"},
    { type: "mp4", file: "//videos.electroteque.org/bitrate/big_buck_bunny_2000k.mp4"},
    { type: "ogg", file: "//videos.electroteque.org/bitrate/big_buck_bunny_2000k.ogv"},
    { type: "rtmp", file: "mp4:bitrate/big_buck_bunny_2000k.mp4"}
    ],
    streamer: "rtmp://rtmp.electroteque.org/cfx/st"
    }
    ],
    plugins: {
    "https://static.electroteque.org/js/jw7/snapshot-4.2.0.js": {
    s3url: "//bucket.s3-region.amazonaws.com",
    s3: {
    "Content-Type":"image\/jpeg",
    "acl":"public-read",
    "success_action_status":"201",
    "policy":"generated policy",
    "X-amz-credential":"accesskey\/timestamp\/region\/s3\/aws4_request",
    "X-amz-algorithm":"AWS4-HMAC-SHA256",
    "X-amz-date":"20160629T081455Z",
    "X-amz-signature":"generatedsignature",
    "key":"${filename}"
    },
    type: "jpeg",
    quality: 0.8,
    //multiple dimensions
    dimensions: [
    { width: 600 },
    { width: 180, thumbnail: true }
    ],
    //post as multiple file uploads
    postfiles: true,
    dockButtonUrl: "images/snapshoticon.png",
    previewClass: "snapshot size1",
    thumbPreviewClass: "snapshot size2",
    dimensions: [
    //configure thumbnail width to auto scale height to
    { width: 180, thumbnail: true }
    ],
    //html5 only
    originbaseurl: "http://crossorigin.electroteque.org/video/"
    }
    }
    });

    });

PLUpload Example

For customisable browser uploading and legacy support, PLUpload options are possible.

Instead of supplying backend upload urls, the captured image data can be obtained from the complete event and used for uploading images via PLUpload



    (function(jwplayer) {

    var uploader = new plupload.Uploader({

    runtimes: "html5,flash",


    url : "http://path/to/server",

    multipart: true,

    //post params
    multipart_params: {

    },

    browse_button: "hiddenButton",
    file_data_name: 'file',

    filters : {
    //min width
    min_img_width: 400,
    // Maximum file size
    max_file_size : '10mb',
    // Specify what files to browse for
    mime_types: [
    {title : "Image files", extensions : "png,jpg,jpeg"}
    ]
    },
    //chunk_size: '200kb',
    max_retries: 3,
    //max_retries: 1,
    chunks : {
    size: '1mb',
    send_chunk_number: false // set this to true, to send chunk and total chunk numbers instead of offset and total bytes
    },
    flash_swf_url : '/static/script/plupload/Moxie.swf',
    // Needed for the Flash environment to work.
    urlstream_upload: true

    });

    //plupload.addFileFilter('min_img_width', this.minWidthFilter);

    uploader.init();

    uploader.bind( "Error", function (up, event) {
    console.log(event);
    });

    uploader.bind( "PostInit", function() {
    console.log("init");
    });

    uploader.bind( "FilesAdded", this.onFilesAdded.bind(this));

    uploader.bind('BeforeUpload', onBeforeUpload = function(up, file) {


    });

    uploader.bind('UploadFile', onUploadFile = function(up, file) {
    console.log("Upload started");
    });


    uploader.bind('UploadProgress',onUploadProgress = function(up, file) {
    console.log("Uploading", up.total.percent + "%");


    });

    uploader.bind('UploadComplete', onUploadsComplete = function(up, file) {
    console.log("File Uploads Complete");

    });


    uploader.bind('FileUploaded', onFileUploaded = function(up, file) {
    console.log("File Upload Complete", file)


    });




    var player = jwplayer("player").setup({
    flashplayer: "jwplayer.flash.swf",
    width: 660,
    height: 350,
    debug: true,

    playlist: [
    {
    "snapshotnames": [
    "test2.jpg",
    "test2-thumb.jpg"

    ],
    sources: [
    { type: "webm", file: "//videos.electroteque.org/bitrate/big_buck_bunny_2000k.webm"},
    { type: "mp4", file: "//videos.electroteque.org/bitrate/big_buck_bunny_2000k.mp4"},
    { type: "ogg", file: "//videos.electroteque.org/bitrate/big_buck_bunny_2000k.ogv"},
    { type: "rtmp", file: "mp4:bitrate/big_buck_bunny_2000k.mp4"}
    ],
    streamer: "rtmp://rtmp.electroteque.org/cfx/st"
    }
    ],
    plugins: {
    "https://static.electroteque.org/js/jw7/snapshot-4.2.0.js": {
    type: "jpeg",
    quality: 0.8,
    //multiple dimensions
    dimensions: [
    { width: 600 },
    { width: 180, thumbnail: true }
    ],
    //post as multiple file uploads
    postfiles: true,
    dockButtonUrl: "images/snapshoticon.png",
    previewClass: "snapshot size1",
    thumbPreviewClass: "snapshot size2",
    dimensions: [
    //configure thumbnail width to auto scale height to
    { width: 180, thumbnail: true }
    ],
    //html5 only
    originbaseurl: "http://crossorigin.electroteque.org/video/"
    }
    }
    });

    player.on("ready",function() {
    player.on("capturecomplete", function(data) {

        var imageFiles = data.imagefiles;

        for (var i = 0; i < imagefiles.length; i++) {

            var image = imageFiles[i];

            var file = new plupload.File(
            new o.File(null, {
            name: image.name,
            data: image.data
            })
            );



            uploader.addFile( file );
            uploader.start();
        }

    }).on("captureerror", function(error) {
    console.log("Capture Error: ", error);
    });

    });





    });