mep_feature_time_rail_thumbnails 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 581863f9c3305a8e58bab3fd847f0ca4749057ab
4
+ data.tar.gz: 805a293d56f27f0331601cddb794444564212403
5
+ SHA512:
6
+ metadata.gz: e0ad1312a6e0028608934e253ca0e065fc72e7a36cdeaa0d93bc5f27be8885b6277919236ee7f8ccaa52f2c6cdade1df701d624c8d42e073fa88eb2491c92034
7
+ data.tar.gz: cef2e3b4387e7696ab2a6e032ddb9a1221c2d8c69e4185ae33b013e0aa1a22b44cf956ca3dfdad0a6bc4e1b3e8065cbb37ed874089cc2c544dd9d01545c39ed4
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2014 North Carolina State Univesity
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # MediaElement.js Plugin for Preview Thumbnails
2
+
3
+ Hover over the time rail on a [MediaElement.js](http://mediaelementjs.com/) player, and see video thumbnails.
4
+
5
+ ## Use
6
+
7
+ To use this feature you will first need to create an image sprite and a metadata WebVTT file.
8
+
9
+ ### Create an Image Sprite
10
+
11
+ The idea is to take a snapshot of your video every 5 seconds and then stitch the images together into a sprite. This means that only one image file needs to be requested from the server and switching between thumbnails can be very quick.
12
+
13
+ Here's one way you could create the image sprite using ffmpeg and montage (from ImageMagick):
14
+
15
+ ```
16
+ ffmpeg -i "video-name.mp4" -f image2 -vf fps=fps=1/5 video-name-%05d.jpg
17
+ montage video-name*jpg -tile 5x -geometry 150x video-name-sprite.jpg
18
+ ```
19
+
20
+ First ffmpeg takes a snapshot of your video every 5 seconds. Then montage reduces each image to 150px across and tiles them from left to right 5 across.
21
+
22
+ ### Create a WebVTT metadata file
23
+
24
+ Once you have the image sprite you'll also need to create a [WebVTT](http://docs.webplatform.org/wiki/concepts/VTT_Captioning) metadata file that contains the URL to your image sprite. For each time range of 5 seconds the URL is given including a [spatial Media Fragment](http://www.w3.org/TR/media-frags/) hash. This gives information about where in your sprite to look for the thumbnail for that time range. Here's an example of what one looks like:
25
+
26
+ ```
27
+ WEBVTT
28
+
29
+ 00:00:00.000 --> 00:00:05.000
30
+ http://example.com/video-name-sprite.jpg#xywh=0,0,150,100
31
+
32
+ 00:00:05.000 --> 00:00:10.000
33
+ http://example.com/video-name-sprite.jpg#xywh=150,0,150,100
34
+
35
+ 00:00:10.000 --> 00:00:15.000
36
+ http://example.com/video-name-sprite.jpg#xywh=300,0,150,100
37
+
38
+ 00:00:15.000 --> 00:00:20.000
39
+ http://example.com/video-name-sprite.jpg#xywh=450,0,150,100
40
+
41
+ 00:00:20.000 --> 00:00:25.000
42
+ http://example.com/video-name-sprite.jpg#xywh=600,0,150,100
43
+
44
+ 00:00:25.000 --> 00:00:30.000
45
+ http://example.com/video-name-sprite.jpg#xywh=0,100,150,100
46
+ ```
47
+
48
+ #### Current Sprite Limitations
49
+ - All the images embedded in the sprite should have exactly the same dimensions. The styling for the thumbnail hover area is calculated based on the dimensions of the first URL in the WebVTT file.
50
+ - Images should only be taken every 5 seconds. While this ought to be configurable in the future it currently is not.
51
+
52
+ ### Markup
53
+
54
+ Add a new track element to your video element like the following:
55
+
56
+ ```html
57
+ <track kind="metadata" class="time-rail-thumbnails" src="http://example.com/video-name-sprite.vtt"></track>
58
+ ```
59
+
60
+ The kind attribute must be "metadata" and the class must be "time-rail-thumbnails". The WebVTT file should also be accessible via an AJAX request, so either have it on the same domain or allow cross-origin requests.
61
+
62
+ ### Initialization
63
+
64
+ Add 'timerailsthumbnails' as the last feature when initializing the mediaelement player:
65
+
66
+ ```javascript
67
+ $('video').mediaelementplayer({
68
+ features: ['playpause','progress','current','duration','tracks','volume', 'timerailthumbnails']
69
+ });
70
+ ```
71
+
72
+ ## Installation
73
+
74
+ This JavaScript plugin is made available as both a Rails Engine gem for the asset pipeline (unreleased) and a bower package. Choose your poison.
75
+
76
+ ### Rails
77
+
78
+ Include it in your Gemfile:
79
+ ```ruby
80
+ gem 'mep_feature_time_rail_thumbnails', git: 'git@github.com:jronallo/mep-feature-time-rail-thumbnails.git'
81
+ ```
82
+
83
+ Add it to your application.js:
84
+ ```javascript
85
+ //= require mep-feature-time-rail-thumbnails
86
+ ```
87
+
88
+ ### Bower
89
+
90
+ Install with bower:
91
+ ```
92
+ bower i mep_feature_time_rail_thumbnails
93
+ ```
94
+
95
+ The file you want is at `bower_components/mep_feature_time_rail_thumbnails/vendor/assets/javascripts/mep-feature-time-rail-thumbnails.js`
96
+
97
+ ## TODO
98
+
99
+ - Make the interval of thumbnails configurable or really use the timestamps in the WebVTT file rather than relying on 5 second increments.
100
+ - Allow to work over HTTP and HTTPS.
101
+
102
+ ## Author
103
+
104
+ Jason Ronallo
105
+
106
+ ## License
107
+
108
+ This project rocks and uses MIT-LICENSE.
@@ -0,0 +1,4 @@
1
+ require "mep_feature_time_rail_thumbnails/engine"
2
+
3
+ module MepFeatureTimeRailThumbnails
4
+ end
@@ -0,0 +1,5 @@
1
+ module MepFeatureTimeRailThumbnails
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace MepFeatureTimeRailThumbnails
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module MepFeatureTimeRailThumbnails
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,126 @@
1
+ (function($) {
2
+
3
+ $.extend(MediaElementPlayer.prototype, {
4
+ buildtimerailthumbnails : function(player, controls, layers, media) {
5
+ if (!player.isVideo)
6
+ return;
7
+
8
+ function getVttCues(url) {
9
+ var vtt,
10
+ parser = new WebVTT.Parser(window, WebVTT.StringDecoder()),
11
+ cues = [];
12
+
13
+ // FIXME: Is there a way to do this with promises?
14
+ $.ajax({
15
+ url: url,
16
+ async: false,
17
+ success: function(data){
18
+ vtt = data;
19
+ },
20
+ error:function (xhr, ajaxOptions, thrownError){
21
+ if(xhr.status==404) {
22
+ vtt = null;
23
+ }
24
+ }
25
+ });
26
+ if (vtt) {
27
+ parser.oncue = function(cue) {
28
+ cues.push(cue);
29
+ };
30
+ parser.parse(vtt);
31
+ parser.flush();
32
+ }
33
+ return cues;
34
+ }
35
+
36
+ function parseMediaFragmentHash(url) {
37
+ var hash = url.substring(url.indexOf('#')+1);
38
+ return hash.split('=')[1].split(',');
39
+ }
40
+
41
+ function setThumbnailImage(url) {
42
+ $('.mejs-plugin-time-float-thumbnail').css('background-image','url(' + url.split('#')[0] + ')');
43
+ }
44
+
45
+ var
46
+ mediaContainer = player.container.find('.mejs-mediaelement').parent(),
47
+ element_to_observe = player.container.find('.mejs-time-float-current')[0],
48
+ video_thumbnail_vtt_url,
49
+ cues,
50
+ preview_thumbnails_track = mediaContainer.find("track[kind='metadata'].time-rail-thumbnails");
51
+
52
+ if (preview_thumbnails_track.length > 0) {
53
+ video_thumbnail_vtt_url = preview_thumbnails_track.attr('src');
54
+ } else {
55
+ return;
56
+ }
57
+ cues = getVttCues(video_thumbnail_vtt_url);
58
+
59
+ // If there is only one cue then there's no need to show thumbnails at all so don't do anything.
60
+ if (cues.length > 1) {
61
+ // Set up the container to hold the thumbnail.
62
+ var time_float = mediaContainer.find('.mejs-time-float');
63
+ time_float.prepend('<span class="mejs-plugin-time-float-thumbnail"></span>');
64
+
65
+ // Set necessary styles.
66
+ var xywh = parseMediaFragmentHash(cues[0].text);
67
+ var x = xywh[0];
68
+ var y = xywh[1];
69
+ var w = xywh[2];
70
+ var h = xywh[3];
71
+ var new_height = parseInt(h) + time_float.height();
72
+ time_float.css('top', '-' + new_height + 'px');
73
+ time_float.find('.mejs-time-float-corner').css('top', new_height - 3 + 'px');
74
+ time_float.css('height', 'auto');
75
+ time_float.css('width', w + 'px');
76
+ time_float.find('.mejs-time-float-current').css('position', 'static');
77
+ time_float.find('.mejs-plugin-time-float-thumbnail').css('position', 'static');
78
+
79
+ setThumbnailImage(cues[0].text);
80
+
81
+ // Add an observer to the .mejs-time-float-current and change the thumbnail
82
+ // when the observer is triggered
83
+ var observer = new MutationObserver(function(mutations){
84
+ var time_code_current = $('.mejs-time-float-current').text();
85
+
86
+ var sections = time_code_current.split(':');
87
+ if (sections.length < 3) {
88
+ time_code_current = "00:" + time_code_current;
89
+ }
90
+
91
+ // If the mouse is hovering over the 0 seconds mark, then show the first frame.
92
+ // Otherwise show something deeper into the video.
93
+ var seconds = mejs.Utility.timeCodeToSeconds(time_code_current),
94
+ cue;
95
+ if (seconds == 0) {
96
+ cue = cues[0];
97
+ } else {
98
+ // FIXME: Change 5 to be configurable for the number of tiles across
99
+ // or actually look up the time cues to see which cue to look into.
100
+ var tile = Math.floor(seconds / 5);
101
+ cue = cues[tile + 1];
102
+ }
103
+
104
+ // The text of the cue will be the background image of the thumbnail container.
105
+ setThumbnailImage(cue.text);
106
+
107
+ // Use the spatial media fragment hash of the url to determine the coordinates and size
108
+ // of the image to be displayed.
109
+ var xywh = parseMediaFragmentHash(cue.text);
110
+ var x = xywh[0];
111
+ var y = xywh[1];
112
+ var w = xywh[2];
113
+ var h = xywh[3];
114
+
115
+ // Set the background position and height and width.
116
+ $('.mejs-plugin-time-float-thumbnail').css('background-position', '-' + x + 'px -' + y + 'px' );
117
+ $('.mejs-plugin-time-float-thumbnail').css('height', h);
118
+ $('.mejs-plugin-time-float-thumbnail').css('width', w);
119
+
120
+ });
121
+
122
+ observer.observe(element_to_observe, {attributes: true, childList: true, characterData: true, subtree:true});
123
+ }
124
+ }
125
+ });
126
+ })(mejs.$);
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mep_feature_time_rail_thumbnails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jason Ronallo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-05-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 3.2.17
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 3.2.17
27
+ description: Add a thumbnail preview to the MediaElement.js player.
28
+ email:
29
+ - jronallo@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - MIT-LICENSE
35
+ - README.md
36
+ - lib/mep_feature_time_rail_thumbnails.rb
37
+ - lib/mep_feature_time_rail_thumbnails/engine.rb
38
+ - lib/mep_feature_time_rail_thumbnails/version.rb
39
+ - vendor/assets/javascripts/mep-feature-time-rail-thumbnails.js
40
+ homepage: https://github.com/jronallo/mep-feature-time-rail-thumbnails
41
+ licenses: []
42
+ metadata: {}
43
+ post_install_message:
44
+ rdoc_options: []
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ requirements: []
58
+ rubyforge_project:
59
+ rubygems_version: 2.2.2
60
+ signing_key:
61
+ specification_version: 4
62
+ summary: MediaElement.js Plugin for Preview Thumbnails
63
+ test_files: []