Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jmrunge/image support #198

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion ffmpeg/ffmpeg.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,17 @@ function FFMPEG (opts) {

FFMPEG.prototype.run = function (orig, dest, opts, callback) {
var stdout, stderr;

var seconds;
if (opts.seconds === undefined)
seconds = 5;
else
seconds = opts.seconds;

this.proc = _spawnProcess (['-i',
orig,
'-r', 1,
'-ss', 5,
'-ss', seconds,
'-vcodec', 'mjpeg',
'-vframes', '1',
'-an',
Expand Down
31 changes: 31 additions & 0 deletions media_types.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
var _ = require('underscore')
;
module.exports = {
types: [{
type: 'image',
seconds: 0,
isMedia: function(filename) {
return filename.match(/\.(bmp|gif|jpg|png|yuv|pix|dpx|exr|jpeg|pam|pbm|pcx|pgm|pic|ppm|ptx|sgi|tif|tiff|webp|xbm|xwd)$/i);
}
},
{
type: 'video',
seconds: 5,
isMedia: function(filename) {
return filename.match(/\.(webm|mp4|flv|avi|mpeg|mpeg2|mpg|mov|mkv|ogm|ogg)$/i);
}
}],
isMedia: function(filename) {
return _.some(this.types, function(type) {
return type.isMedia(filename);
});
},
getType: function(filename) {
return _.find(this.types, function(type) {
return type.isMedia(filename);
});
},
getSeconds: function(type) {
return _.findWhere(this.types, {type: type}).seconds;
}
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe in the future we can use something like node-mime
https://github.com/broofa/node-mime

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its nice, but I dont know if all the image or video types identified by node-mime are supported by ffmpeg. And as for using our custom types file, I think perhaps is better to use then our own "mime" handling. Sure it should be moved to common in the very near future so mosto and caspa use the same code.

85 changes: 84 additions & 1 deletion public/js/views/medialist.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,12 @@ window.MediaListView = function(options){
self.collection.remove(item);
self.filter(filters);
}


this.editItem = function(item) {
console.log('Editing Piece', item);
if (item.type() === 'image')
self.editImage(item);
}

this.__filters = ko.observable();
this.filter = ko.computed({
Expand Down Expand Up @@ -179,6 +184,47 @@ window.MediaListView = function(options){
pieces.add(model, {at: arg.targetIndex});
}
},

editImage: function(item) {
var self = this;

var title = i18n.gettext('Image Edit');
var duration = i18n.gettext('Duration (HH:mm:ss):');
var duration_value = moment(item.durationraw(), 'HH:mm:ss.SSS').format('HH:mm:ss');
var prompt = new ImageEditPrompt(
{ title: title,
duration: duration,
duration_value: duration_value,
submitCallback: function (length) {
console.log("Selected YES");
if(length) {
var l = length.match(/(\d{2}):(\d{2}):(\d{2})/);
if (l === null) {
var description = i18n.gettext('Wrong duration format');
self.alert(description);
} else {
l.shift();
var fmt_length = l[0] + ':' + l[1] + ':' + l[2] + '.00';
console.log("Changing length: ", fmt_length);
item.durationraw(fmt_length);
}
} else {
var description = i18n.gettext('You must enter length');
self.alert(description);
}
},
cancelCallback: function() {
return;
} }).render().el;
$('#modal').html(prompt);
window.scrollTo(0,0);
},
alert: function(description) {
var title = i18n.gettext('Alert');
var description = description || i18n.gettext('Wait there was a problem');
$('#modal').html(new ModalAlert({ title: title, description: description }).render().el);
window.scrollTo(0,0);
},
});

this.search_view = new SearchView({
Expand Down Expand Up @@ -287,3 +333,40 @@ window.MediaListView = function(options){
};
}

var ImageEditPrompt = Backbone.Modal.extend({
initialize: function (options) {
this.options = options || {};
},
template: function() {
var parse_tpl = template.imagepieceedit(this.options);
return _.template(parse_tpl);
},
submitEl: '.submit',
cancelEl: '.cancel',
events: {
"click .submit" : "save",
"keypress input[id=textkey]" : "saveOnEnter",
"click .cancel" : "cancel"
},
save: function () {
this.options.submitCallback($('#duration').val());
},
saveOnEnter: function (e) {
if (e.keyCode != 13) return;
this.save();
},
cancel: function() {
this.options.cancelCallback();
}
});
var ModalAlert = Backbone.Modal.extend({
initialize: function (options) {
this.options = options || {};
},
template: function() {
var parse_tpl = template.alert(this.options);
return _.template(parse_tpl);
},
cancelEl: '.bbm-button'
});

3 changes: 2 additions & 1 deletion routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,8 @@ module.exports = function(app, everyauth) {
'emptyalert',
'timeinfo',
'nowplaying',
'sourceinfo'
'sourceinfo',
'imagepieceedit'
];

var commonTemplates = ['editor',
Expand Down
11 changes: 7 additions & 4 deletions utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ var _ = require('underscore')
, conf = mbc.config.Caspa
, logger = mbc.logger().addLogger('caspa_util')
, collections = mbc.config.Common.Collections
, media_types = require('./media_types.js')
;

var _exists = fs.exists || require('path').exists;
Expand Down Expand Up @@ -85,6 +86,7 @@ utils.prototype.sc_pool = new fp.Pool({size: 1}, function (media, callback, done
var f = new ffmpeg();
f.run (media.file, dest, {
size: '150x100',
seconds: media_types.getSeconds(media.type),
onCodecData: function(metadata) {
logger.info('here');
if (!callback)
Expand All @@ -95,6 +97,7 @@ utils.prototype.sc_pool = new fp.Pool({size: 1}, function (media, callback, done
metadata.file = media.file;
metadata.stat = media.stat;
metadata.checksum = media._id;
metadata.type = media.type;
callback (metadata);
}
}, function(retcode, fds) {
Expand Down Expand Up @@ -125,7 +128,7 @@ utils.prototype.parse_pool = function () {
if (stat === item.stat) return (done(item));
else item.stat = stat;
} else {
item = { _id: md5 , file: file, stat: stat};
item = { _id: md5 , file: file, stat: stat, type: media_types.getType(file).type};
}

return done(item);
Expand Down Expand Up @@ -157,8 +160,9 @@ utils.prototype.scrape_files = function (path, callback) {
.on('file', function (root, stat, next) {
var file = root + '/' + stat.name;
next();
if (! stat.name.match(/\.(webm|mp4|flv|avi|mpeg|mpeg2|mpg|mov|mkv|ogm|ogg)$/i)) {
var error = new Error('file not a vid : ' + stat.name);

if (!media_types.isMedia(stat.name)) {
var error = new Error('file type not supported: ' + stat.name);
logger.error(error.toString());
return error;
}
Expand All @@ -169,7 +173,6 @@ utils.prototype.scrape_files = function (path, callback) {
logger.debug('parsed: ' + stat.name, res);
self.sc_pool.task(res, callback, function (err, res) {return res});
});

})
.on('end', function () {
logger.info("all done");
Expand Down
12 changes: 12 additions & 0 deletions views/templates/imagepieceedit.jade
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
- var submit = i18n.gettext("Submit")
- var cancel = i18n.gettext("Cancel")

.bbm-modal__topbar
h3.bbm-modal__title= title
.bbm-modal__section
fieldset
legend.editor= duration
input#duration(type="text", style="width:200px", value=duration_value)
.bbm-modal__bottombar
a.bbm-button.submit(href="#")= submit
a.bbm-button.cancel(href="#")= cancel
10 changes: 10 additions & 0 deletions views/templates/medialist.jade
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ block content
- var thumbnail = i18n.gettext('Thumbnail')
- var media_info = i18n.gettext('Media info')

#modal

#media-list.infinit-panel
- if (!fixed)
button.close.kill-media-list(type='button', data-dismiss='alert') ×
Expand Down Expand Up @@ -86,13 +88,21 @@ block content
td.center
- if (!is_playlist)
- var target = "attr:{href: '/media/'+checksum().split('-')[0]}";
- else
- var target = "attr:{href: '#'}, click: $root.editItem, clickBubble: false";
a.plain(data-bind=target)
img(width="150",height="100",data-bind="attr:{ src: checksum() ? '/sc/'+checksum().split('-')[0]+'.jpg' : '/pics/generic.jpg' }")
td
- if (is_playlist)
button.close.remove-media(type='button', data-bind='click: $root.removeItem, clickBubble: false') ×
h5(data-bind="text: name")
h5(data-bind="text: stat().name ? stat().name : file")

span.label.type
<!-- TODO: Use type attr from piece -->
span(data-bind="text: type")
span=' '

span.label.label-warning.format
i.icon-time.icon-white
span(data-bind="text: durationraw")
Expand Down
2 changes: 1 addition & 1 deletion views/templates/mediaview.jade
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
.row
.span6
.control-group
- var items = {md5: _id, 'File Name': file, Duration: durationraw, Format: video.container, Audio: audio.codec, Video:video.codec}
- var items = {md5: _id, 'Type': type, 'File Name': file, Duration: durationraw, Format: video.container, Audio: audio.codec, Video:video.codec}
each v, k in items
- var Item = k.charAt(0).toUpperCase() + k.slice(1)

Expand Down