From a1deb20f97666a392f0d7e4a7f2142674bc08a7e Mon Sep 17 00:00:00 2001 From: rolux Date: Wed, 18 May 2011 20:30:58 +0200 Subject: [PATCH] video editor improvements --- demos/videoeditor/js/videoeditor.js | 6 ++-- .../Ox.UI/js/Video/Ox.BlockVideoTimeline.js | 22 +++++++++++-- .../Ox.UI/js/Video/Ox.LargeVideoTimeline.js | 25 +++++++------- .../Ox.UI/js/Video/Ox.SmallVideoTimeline.js | 10 ++++++ .../js/Video/Ox.SmallVideoTimelineImage.js | 14 +++----- source/Ox.UI/js/Video/Ox.VideoEditor.js | 21 +++++++----- source/Ox.UI/js/Video/Ox.VideoPlayer.js | 33 +++++++++++++------ .../Ox.UI/themes/classic/svg/symbolEmbed.svg | 8 ++--- 8 files changed, 89 insertions(+), 50 deletions(-) diff --git a/demos/videoeditor/js/videoeditor.js b/demos/videoeditor/js/videoeditor.js index 1ba72fb5..e2520906 100644 --- a/demos/videoeditor/js/videoeditor.js +++ b/demos/videoeditor/js/videoeditor.js @@ -11,15 +11,15 @@ Ox.load('UI', { annotationsSize: 256, duration: 6336.08, find: 'dode', + getFrameURL: function(position, width) { + return 'http://next.0xdb.org/0393109/frame/' + width + '/' + position + '.jpg' + }, getLargeTimelineImageURL: function(i) { return 'http://next.0xdb.org/0393109/timelines/timeline.64.' + i + '.png'; }, getSmallTimelineImageURL: function(i) { return 'http://next.0xdb.org/0393109/timelines/timeline.16.' + i + '.png'; }, - getVideoImageURL: function(i) { - return 'png/0393109.png'; - }, height: window.innerHeight - 129, 'in': 3128.76, out: 3130.72, diff --git a/source/Ox.UI/js/Video/Ox.BlockVideoTimeline.js b/source/Ox.UI/js/Video/Ox.BlockVideoTimeline.js index 7ceb91a8..a1e6a90c 100644 --- a/source/Ox.UI/js/Video/Ox.BlockVideoTimeline.js +++ b/source/Ox.UI/js/Video/Ox.BlockVideoTimeline.js @@ -51,7 +51,7 @@ Ox.BlockVideoTimeline = function(options, self) { results: self.options.results, subtitles: self.options.subtitles, timeline: self.options.getImageURL, - width: Math.ceil(self.options.duration), + width: Math.round(self.options.duration), type: self.options.type }); @@ -113,7 +113,7 @@ Ox.BlockVideoTimeline = function(options, self) { .css({ position: 'absolute', top: '2px', - width: Math.ceil(self.options.duration) + 'px', + width: Math.round(self.options.duration) + 'px', height: '20px', marginLeft: (-i * self.options.width) + 'px', //background: 'rgba(255, 0, 0, 0.1)', @@ -195,6 +195,20 @@ Ox.BlockVideoTimeline = function(options, self) { }); } + function setPoint(point) { + setPointMarker(point); + self.$image.options(point, self.options[point]); + self.$lines.forEach(function($line, i) { + $($line.children()[0]).replaceWith( + self.$images[i] = self.$image.clone() + .css({ + position: 'absolute', + marginLeft: (-i * self.options.width) + 'px' + }) + ); + }); + } + function setPointMarker(point) { var position = Math.round(self.options[point]); self.$pointMarker[point].css({ @@ -241,7 +255,9 @@ Ox.BlockVideoTimeline = function(options, self) { } self.setOption = function(key, value) { - if (key == 'position') { + if (key == 'in' || key == 'out') { + setPoint(key) + } else if (key == 'position') { setPositionMarker(); } else if (key == 'width') { setWidth(); diff --git a/source/Ox.UI/js/Video/Ox.LargeVideoTimeline.js b/source/Ox.UI/js/Video/Ox.LargeVideoTimeline.js index 51e39676..e8384320 100644 --- a/source/Ox.UI/js/Video/Ox.LargeVideoTimeline.js +++ b/source/Ox.UI/js/Video/Ox.LargeVideoTimeline.js @@ -39,7 +39,7 @@ Ox.LargeVideoTimeline = function(options, self) { $.extend(self, { $cuts: [], - $markerPoint: {}, + $pointMarker: {}, $tiles: {}, $tooltip: new Ox.Tooltip({ animate: false @@ -82,13 +82,13 @@ Ox.LargeVideoTimeline = function(options, self) { ['in', 'out'].forEach(function(point) { var titlecase = Ox.toTitleCase(point); - self.$markerPoint[point] = $('') + self.$pointMarker[point] = $('') .addClass('OxMarkerPoint' + titlecase) .attr({ src: Ox.UI.PATH + 'png/videoMarker' + titlecase + '.png' }) .appendTo(self.$timeline); - setMarkerPoint(point); + setPointMarker(point); }); setWidth(); @@ -132,18 +132,18 @@ Ox.LargeVideoTimeline = function(options, self) { updateTooltip(); } - function setMarkerPoint(point) { - self.$markerPoint[point].css({ - left: (self.options[point] * self.fps) + 'px' - }); - } - function setMarker() { self.$markerPosition.css({ left: (self.center - 4) + 'px', }); } + function setPointMarker(point) { + self.$pointMarker[point].css({ + left: (self.options[point] * self.fps) + 'px' + }); + } + function setPosition() { self.tile = parseInt(self.options.position * self.fps / self.tileWidth); self.$timeline.css({ @@ -215,9 +215,10 @@ Ox.LargeVideoTimeline = function(options, self) { } self.setOption = function(key, value) { - if (key == 'points') { - setMarkerPoint('in'); - setMarkerPoint('out'); + if (key == 'in') { + setPointMarker('in'); + } else if (key == 'out') { + setPointMarker('out'); } else if (key == 'position') { setPosition(); } else if (key == 'subtitles') { diff --git a/source/Ox.UI/js/Video/Ox.SmallVideoTimeline.js b/source/Ox.UI/js/Video/Ox.SmallVideoTimeline.js index 689828e1..5a0aa762 100644 --- a/source/Ox.UI/js/Video/Ox.SmallVideoTimeline.js +++ b/source/Ox.UI/js/Video/Ox.SmallVideoTimeline.js @@ -245,6 +245,16 @@ Ox.SmallVideoTimeline = function(options, self) { self.$image.options({ duration: value }); + } else if (key == 'in') { + self.$image.options({ + 'in': value + }); + setPointMarker('in'); + } else if (key == 'out') { + self.$image.options({ + out: value + }); + setPointMarker('out'); } else if (key == 'paused') { self.$positionMarkerRing.css({ borderColor: 'rgba(255, 255, 255, ' + (self.options.paused ? 0.5 : 1) + ')' diff --git a/source/Ox.UI/js/Video/Ox.SmallVideoTimelineImage.js b/source/Ox.UI/js/Video/Ox.SmallVideoTimelineImage.js index 157b1972..627df94b 100644 --- a/source/Ox.UI/js/Video/Ox.SmallVideoTimelineImage.js +++ b/source/Ox.UI/js/Video/Ox.SmallVideoTimelineImage.js @@ -19,11 +19,6 @@ Ox.SmallVideoTimelineImage = function(options, self) { width: self.options.width + 'px' }); - // fixme: unless we do a block timeline, - // we can always use a single 1920 png - // fixme: timeline doesn't have to go through canvas at all, - // just use one or more images - self.images = Ox.isString(self.options.timeline) ? 1 : Math.ceil(self.options.duration / 3600); self.imageWidth = Ox.isString(self.options.timeline) ? @@ -169,16 +164,17 @@ Ox.SmallVideoTimelineImage = function(options, self) { right = Math.round( subtitle.out / self.options.duration * self.imageWidth ) + 1, - top = bottom - subtitle.text.split('\n').length - 2; + top = bottom - subtitle.text.split('\n').length - 3; Ox.loop(left, right, function(x) { Ox.loop(top, bottom, function(y) { - var color = (y == top || y == bottom - 1) ? - [0, 0, 0] : [255, 255, 255], + var color = y == top ? [0, 0, 0, 0] : + (y == top + 1 || y == bottom - 1) ? + [0, 0, 0, 128] : [255, 255, 255, 128], index = x * 4 + y * 4 * width; data[index] = color[0]; data[index + 1] = color[1]; data[index + 2] = color[2]; - data[index + 3] = 128; + data[index + 3] = color[3]; }); }); }); diff --git a/source/Ox.UI/js/Video/Ox.VideoEditor.js b/source/Ox.UI/js/Video/Ox.VideoEditor.js index ef062cfa..c6d11d4e 100644 --- a/source/Ox.UI/js/Video/Ox.VideoEditor.js +++ b/source/Ox.UI/js/Video/Ox.VideoEditor.js @@ -20,9 +20,9 @@ Ox.VideoEditor = function(options, self) { find: '', frameURL: function() {}, fps: 25, + getFrameURL: null, getLargeTimelineImageURL: null, getSmallTimelineImageURL: null, - getVideoImageURL: null, 'in': 0, height: 0, largeTimeline: true, @@ -75,7 +75,7 @@ Ox.VideoEditor = function(options, self) { setPoint('in'); }, key_left: function() { - movePositionBy(-1); + movePositionBy(-0.04); }, key_o: function() { setPoint('out'); @@ -85,7 +85,7 @@ Ox.VideoEditor = function(options, self) { }, key_p: playInToOut, key_right: function() { - movePositionBy(1); + movePositionBy(0.04); }, key_s: function() { // toggleSize @@ -100,7 +100,7 @@ Ox.VideoEditor = function(options, self) { movePositionBy(self.options.duration); }, key_shift_left: function() { - movePositionBy(-0.04); + movePositionBy(1); //movePositionBy(-60); }, key_shift_i: function() { @@ -110,11 +110,11 @@ Ox.VideoEditor = function(options, self) { goToPoint('out'); }, key_shift_right: function() { - movePositionBy(0.04); + movePositionBy(1); //movePositionBy(60); }, key_shift_up: function() { - movePositionBy(-self.options.duration); + movePositionBy(-self.options.position); }, key_slash: function() { select('cut'); @@ -144,7 +144,7 @@ Ox.VideoEditor = function(options, self) { ['play', 'in', 'out'].forEach(function(type, i) { self.$player[i] = new Ox.VideoPlayer({ controlsBottom: type == 'play' ? - ['play', 'playInToOut', 'mute', 'size', 'space', 'position'] : + ['play', 'playInToOut', 'volume', 'size', 'space', 'position'] : ['goto', 'set', 'space', 'position'], duration: self.options.duration, externalControls: true, @@ -160,7 +160,7 @@ Ox.VideoEditor = function(options, self) { showMilliseconds: 2, subtitles: self.options.subtitles, type: type, - video: type == 'play' ? self.options.video : self.options.getVideoImageURL, + video: type == 'play' ? self.options.video : self.options.getFrameURL, width: self.sizes.player[i].width }) .css({ @@ -512,8 +512,11 @@ Ox.VideoEditor = function(options, self) { } function setPoint(point) { + var otherPoint = point == 'in' ? 'out' : 'in'; self.options[point] = self.options.position; - self.$player[0].options(point, self.options[point]); + self.$player.forEach(function($player) { + $player.options(point, self.options[point]); + }); self.$player[point == 'in' ? 1 : 2].options({ position: self.options[point] }); diff --git a/source/Ox.UI/js/Video/Ox.VideoPlayer.js b/source/Ox.UI/js/Video/Ox.VideoPlayer.js index 17c84972..c986d5f6 100644 --- a/source/Ox.UI/js/Video/Ox.VideoPlayer.js +++ b/source/Ox.UI/js/Video/Ox.VideoPlayer.js @@ -306,8 +306,6 @@ Ox.VideoPlayer = function(options, self) { loadImage(); - self.options[self.options.type] = self.options.position; - } /* @@ -407,11 +405,14 @@ Ox.VideoPlayer = function(options, self) { src: Ox.UI.PATH + 'png/videoMarker' + titleCase + '.png' }) .appendTo(self.$videoContainer); - /* - if (self.options.points[i] == self.options.position) { - self.$pointMarker[point][edge].show(); + // fixme: there's a bug in jquery and/or webkit + // normally, setMarker() should properly .show() + // the in markers of the in player + // or the out markers of the out player, + // but only setting css display seems to work + if (self.options.type == point) { + self.$pointMarker[point][edge].css({display: 'block'}); } - */ }); }); @@ -903,7 +904,7 @@ Ox.VideoPlayer = function(options, self) { ---------------------------------------------------------------------------- */ - if (self.options.enableVolume) { + if (self.options.enableVolume || true) { // fixme self.$volume = $('
') .addClass('OxControls OxVolume') @@ -961,6 +962,8 @@ Ox.VideoPlayer = function(options, self) { } + self.options.type != 'play' && self.options.showMarkers && setMarkers(); + self.results = []; if (self.options.subtitles) { if (Ox.isArray(self.options.subtitles)) { @@ -1386,6 +1389,10 @@ Ox.VideoPlayer = function(options, self) { }); } + function isEqual(a, b) { + return Math.abs(a - b) < 0.001; + } + function loadImage() { self.$video .one({ @@ -1395,7 +1402,7 @@ Ox.VideoPlayer = function(options, self) { } }) .attr({ - src: self.options.video(self.options.position) + src: self.options.video(self.options.position, self.options.width) }); } @@ -1535,13 +1542,15 @@ Ox.VideoPlayer = function(options, self) { } function setMarkers() { + //Ox.print('SET MARKERS', self.options.position, self.options['in'], self.options.out, self.$pointMarker); Ox.forEach(self.$posterMarker, function(marker) { - self.options.position == self.options.posterFrame ? + isEqual(self.options.position, self.options.posterFrame) ? marker.show() : marker.hide(); }); Ox.forEach(self.$pointMarker, function(markers, point) { Ox.forEach(markers, function(marker) { - self.options.position == self.options[point] ? + //Ox.print(self.options.position, self.options[point], isEqual(self.options.position, self.options[point])) + isEqual(self.options.position, self.options[point]) ? marker.show() : marker.hide(); }); }); @@ -1994,12 +2003,16 @@ Ox.VideoPlayer = function(options, self) { toggleFullscreen(); } else if (key == 'height' || key == 'width') { setSizes(); + } else if (key == 'in' || key == 'out') { + self.options.paused && setMarkers(); } else if (key == 'muted') { toggleMuted(); } else if (key == 'paused') { togglePaused(); } else if (key == 'position') { setPosition(value); + } else if (key == 'posterFrame') { + self.options.paused && setMarkers(); } else if (key == 'scaleToFill') { toggleScale(); } diff --git a/source/Ox.UI/themes/classic/svg/symbolEmbed.svg b/source/Ox.UI/themes/classic/svg/symbolEmbed.svg index 47906b13..eae043aa 100644 --- a/source/Ox.UI/themes/classic/svg/symbolEmbed.svg +++ b/source/Ox.UI/themes/classic/svg/symbolEmbed.svg @@ -1,6 +1,6 @@ - - - - + + + + \ No newline at end of file