pandora/static/js/pandora/uploadDialog.js

365 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// vim: et:ts=4:sw=4:sts=4:ft=javascript
'use strict';
pandora.ui.uploadDialog = function(data) {
var cancelled = false,
file,
selectFile,
$actionButton,
$closeButton,
$content = Ox.Element().css({margin: '16px'}),
$info = $('<div>').css({padding: '4px'})
.html('Please select the video file you want to upload.'),
$progress,
$status = $('<div>').css({padding: '4px', paddingTop: '8px'}),
that = Ox.Dialog({
buttons: [
$closeButton = Ox.Button({
id: 'close',
title: 'Close'
}).bindEvent({
click: function() {
that.triggerEvent('close');
}
}),
$actionButton = Ox.Button({
id: 'action',
title: 'Select Video'
}).bindEvent({
click: function() {
if ($actionButton.options('title') == 'Select Video') {
if (selectVideo()) {
$actionButton.options('title', 'Upload');
}
} else if ($actionButton.options('title') == 'Cancel') {
cancelled = true;
pandora.firefogg && pandora.firefogg.cancel();
pandora.$ui.upload && pandora.$ui.upload.abort();
$actionButton.options('title', 'Select Video');
$closeButton.show();
} else {
$actionButton.options('title', 'Cancel');
$closeButton.hide();
encode();
}
}
})
],
content: $content,
height: 128,
removeOnClose: true,
width: 368,
title: 'Upload Video',
})
.bindEvent({
close: function(data) {
if (pandora.firefogg) {
pandora.firefogg.cancel();
delete pandora.firefogg;
}
that.close();
}
});
// FIXME: is this necessary?
pandora._status = $status;
pandora._info = $info;
if (typeof Firefogg == 'undefined') {
/*
selectFile = $('<input>')
.attr({
type: 'file'
})
.css({
padding: '8px'
})
.on({
change: function(event) {
if (this.files.length) {
file = this.files[0];
if (file.type == 'video/webm') {
$status.html('');
uploadButton.options({
disabled: false
});
} else {
$status.html('Currently only WebM files are supported. (<a href="/help/encoding">Help encoding video</a>)');
}
} else {
uploadButton.options({
disabled: true
});
}
}
})
.appendTo($content);
*/
$info.html(
'Currently, video upload is only supported in '
+ '<a target="_new" href="http://mozilla.org/firefox/">Firefox</a>, with '
+ '<a target="_new" href="http://firefogg.org/">Firefogg</a> installed.<br><br>'
+ 'Alternatively, you can use '
+ '<a target="_new" href="https://wiki.0x2620.org/wiki/pandora_client">pandora_client</a>.'
);
$actionButton.hide();
}
$content.append($info);
$content.append($status);
function aspectratio(ratio) {
var denominator, numerator;
ratio = ratio.split(':');
numerator = ratio[0];
if (ratio.length == 2) {
denominator = ratio[1];
}
if (Math.abs(numerator / denominator - 4/3) < 0.03) {
numerator = 4;
denominator = 3;
} else if (Math.abs(numerator / denominator - 16/9) < 0.02) {
numerator = 16;
denominator = 9;
}
return {
denominator: denominator,
'float': numerator / denominator,
numerator: numerator,
ratio: numerator + ':' + denominator
};
}
function resetProgress() {
$progress = Ox.Progressbar({
progress: 0,
showPercent: true,
showTime: true,
width: 304
});
$status.html('').append($progress);
}
function encode() {
var filename = pandora.firefogg.sourceFilename,
info = JSON.parse(pandora.firefogg.sourceInfo),
item,
oshash = info.oshash;
resetProgress();
pandora.api.addFile({
filename: filename,
id: oshash,
info: info
}, function(result) {
item = result.data.item;
pandora.firefogg.encode(
getEncodingOptions(info),
function(result, file) {
result = JSON.parse(result);
if (result.progress != 1) {
$status.html(cancelled ? 'Encoding cancelled.' : 'Encoding failed.');
delete pandora.firefogg;
return;
}
setTimeout(function() {
//$status.html('uploading... ');
pandora.$ui.upload = pandora.ui.upload(oshash, file)
.bindEvent({
progress: function(data) {
var progress = data.progress || 0;
$progress.options({progress: 0.5 + progress / 2});
},
done: function(data) {
Ox.Request.clearCache();
pandora.UI.set({
item: item,
itemView: 'files'
});
delete pandora.firefogg;
that.close();
}
});
});
},
function(progress) {
progress = JSON.parse(progress).progress || 0;
$progress.options({progress: progress / 2});
}
);
});
}
function getEncodingOptions(info) {
var bpp = 0.17,
dar,
format = pandora.site.video.formats[0],
fps,
options = {},
resolution = Ox.max(pandora.site.video.resolutions);
if (format == 'webm') {
options.videoCodec = 'vp8';
options.audioCodec = 'vorbis';
} else if (format == 'ogv') {
options.videoCodec = 'theora';
options.audioCodec = 'vorbis';
}
if (resolution == 720) {
options.height = 720;
options.samplerate = 48000;
options.audioQuality = 5;
} else if (resolution == 480) {
options.height = 480;
options.samplerate = 44100;
options.audioQuality = 3;
options.channels = 2;
} else if (resolution == 432) {
options.height = 432;
options.samplerate = 44100;
options.audioQuality = 3;
options.channels = 2;
} else if (resolution == 360) {
options.height = 320;
options.samplerate = 44100;
options.audioQuality = 1;
options.channels = 1;
} else if (resolution == 288) {
options.height = 288;
options.samplerate = 44100;
options.audioQuality = 0;
options.channels = 1;
} else if (resolution == 240) {
options.height = 240;
options.samplerate = 44100;
options.audioQuality = 0;
options.channels = 1;
} else if (resolution == 144) {
options.height = 144;
options.samplerate = 22050;
options.audioQuality = -1;
options.audioBitrate = 22;
options.channels = 1;
} else if (resolution == 96) {
options.height = 96;
options.samplerate = 22050;
options.audioQuality = -1;
options.audioBitrate = 22;
options.channels = 1;
}
if (info.video && info.video[0].display_aspect_ratio) {
dar = aspectratio(info.video[0].display_aspect_ratio);
fps = aspectratio(info.video[0].framerate).float;
options.width = parseInt(dar.float * options.height, 10);
options.width += options.width % 2;
// interlaced hdv material is detected with double framerates
if (fps == 50) {
options.framerate = 25;
} else if (fps == 60) {
options.framerate = 30;
}
if (Math.abs(options.width/options.height - dar.float) < 0.02) {
options.aspect = options.width + ':' + options.height;
} else {
options.aspect = dar.ratio;
}
options.videoBitrate = Math.round(
options.height * options.width * fps * bpp / 1000
);
options.denoise = true;
options.deinterlace = true;
} else {
options.noVideo = true;
}
if (info.audio) {
if (options.cannels && info.audio[0].channels < options.channels) {
delete options.channels;
}
} else {
options.noAudio = true;
delete options.samplerate;
delete options.audioQuality;
delete options.channels;
}
options.noUpscaling = true;
if (
(!info.video.length || (
info.video[0].codec == options.videoCodec
&& info.video[0].height <= options.height
))
&& (!info.audio.length || info.audio[0].codec == options.audioCodec)
) {
options = {passthrough: true};
}
return JSON.stringify(options);
}
function formatInfo(info) {
var html = '<b>' + info.path + '</b><br>';
if (info.video && info.video.length > 0) {
var video = info.video[0];
html += video.width + '×' + video.height + ' (' + video.codec + ')';
}
if (
info.video && info.video.length > 0
&& info.audio && info.audio.length > 0
) {
html += ' / ';
}
if (info.audio && info.audio.length > 0) {
var audio = info.audio[0];
html += {1: 'mono', 2: 'stereo', 6: '5.1'}[audio.channels]
+ ' ' + audio.samplerate / 1000 + ' kHz (' + audio.codec + ')';
}
html += '<br>' + Ox.formatValue(info.size, 'B')
+ ' / ' + Ox.formatDuration(info.duration);
return html;
}
function selectVideo() {
cancelled = false;
pandora.firefogg = new Firefogg();
pandora.firefogg.setFormat(pandora.site.video.formats[0]);
if (pandora.firefogg.selectVideo()) {
var info = JSON.parse(pandora.firefogg.sourceInfo),
options = JSON.parse(getEncodingOptions(info)),
oshash = info.oshash,
filename = pandora.firefogg.sourceFilename,
item;
pandora.api.findFiles({
query: {
conditions: [{key: 'oshash', value: oshash}]
},
keys: ['id', 'available']
}, function(result) {
if (
result.data.items.length === 0
|| !result.data.items[0].available
) {
$info.html(formatInfo(info));
$status.html(
options.passthrough
? 'Your video will be uploaded directly.'
: 'Your video will be transcoded before upload.'
);
} else {
pandora.api.find({
query: {
conditions: [{key: 'oshash', value: oshash}]
},
keys: ['id']
}, function(result) {
pandora.UI.set({
item: result.data.items[0].id,
itemView: 'files'
});
delete pandora.firefogg;
that.close();
});
}
});
return true;
}
return false;
}
return that;
};