Faster sniffing
- Sniffing now goes through the old extension-based filter before doing it the bitsniffing way. - Refractored get_media_type_and_manager(filename). - Removed ogg extension from video accepted extensions, audio will take care of that. - Added custom audio player, still WIP,but working. - Added test for sniffing. This only tests for the mediagoblin.media_types.image type, as that is the only one enabled from start.
This commit is contained in:
parent
9743ce886a
commit
a9d84d4cb7
@ -36,16 +36,24 @@ def sniff_media(media):
|
|||||||
Iterate through the enabled media types and find those suited
|
Iterate through the enabled media types and find those suited
|
||||||
for a certain file.
|
for a certain file.
|
||||||
'''
|
'''
|
||||||
media_file = tempfile.NamedTemporaryFile()
|
|
||||||
media_file.write(media.file.read())
|
try:
|
||||||
media.file.seek(0)
|
return get_media_type_and_manager(media.filename)
|
||||||
for media_type, manager in get_media_managers():
|
except FileTypeNotSupported:
|
||||||
_log.info('Sniffing {0}'.format(media_type))
|
_log.info('No media handler found by file extension. Doing it the expensive way...')
|
||||||
if manager['sniff_handler'](media_file, media=media):
|
# Create a temporary file for sniffers suchs as GStreamer-based
|
||||||
_log.info('{0} accepts the file'.format(media_type))
|
# Audio video
|
||||||
return media_type, manager
|
media_file = tempfile.NamedTemporaryFile()
|
||||||
else:
|
media_file.write(media.file.read())
|
||||||
_log.debug('{0} did not accept the file'.format(media_type))
|
media.file.seek(0)
|
||||||
|
|
||||||
|
for media_type, manager in get_media_managers():
|
||||||
|
_log.info('Sniffing {0}'.format(media_type))
|
||||||
|
if manager['sniff_handler'](media_file, media=media):
|
||||||
|
_log.info('{0} accepts the file'.format(media_type))
|
||||||
|
return media_type, manager
|
||||||
|
else:
|
||||||
|
_log.debug('{0} did not accept the file'.format(media_type))
|
||||||
|
|
||||||
raise FileTypeNotSupported(
|
raise FileTypeNotSupported(
|
||||||
# TODO: Provide information on which file types are supported
|
# TODO: Provide information on which file types are supported
|
||||||
@ -91,22 +99,22 @@ def get_media_manager(_media_type):
|
|||||||
|
|
||||||
def get_media_type_and_manager(filename):
|
def get_media_type_and_manager(filename):
|
||||||
'''
|
'''
|
||||||
Get the media type and manager based on a filename
|
Try to find the media type based on the file name, extension
|
||||||
|
specifically. This is used as a speedup, the sniffing functionality
|
||||||
|
then falls back on more in-depth bitsniffing of the source file.
|
||||||
'''
|
'''
|
||||||
if filename.find('.') > 0:
|
if filename.find('.') > 0:
|
||||||
# Get the file extension
|
# Get the file extension
|
||||||
ext = os.path.splitext(filename)[1].lower()
|
ext = os.path.splitext(filename)[1].lower()
|
||||||
else:
|
|
||||||
raise InvalidFileType(
|
|
||||||
_(u'Could not extract any file extension from "{filename}"').format(
|
|
||||||
filename=filename))
|
|
||||||
|
|
||||||
for media_type, manager in get_media_managers():
|
for media_type, manager in get_media_managers():
|
||||||
# Omit the dot from the extension and match it against
|
# Omit the dot from the extension and match it against
|
||||||
# the media manager
|
# the media manager
|
||||||
if ext[1:] in manager['accepted_extensions']:
|
if ext[1:] in manager['accepted_extensions']:
|
||||||
return media_type, manager
|
return media_type, manager
|
||||||
else:
|
else:
|
||||||
raise FileTypeNotSupported(
|
_log.info('File {0} has no file extension, let\'s hope the sniffers get it.'.format(
|
||||||
# TODO: Provide information on which file types are supported
|
filename))
|
||||||
_(u'Sorry, I don\'t support that file type :('))
|
|
||||||
|
raise FileTypeNotSupported(
|
||||||
|
_(u'Sorry, I don\'t support that file type :('))
|
||||||
|
@ -26,4 +26,4 @@ MEDIA_MANAGER = {
|
|||||||
"display_template": "mediagoblin/media_displays/video.html",
|
"display_template": "mediagoblin/media_displays/video.html",
|
||||||
"default_thumb": "images/media_thumbs/video.jpg",
|
"default_thumb": "images/media_thumbs/video.jpg",
|
||||||
"accepted_extensions": [
|
"accepted_extensions": [
|
||||||
"mp4", "mov", "webm", "avi", "3gp", "3gpp", "mkv", "ogv", "ogg"]}
|
"mp4", "mov", "webm", "avi", "3gp", "3gpp", "mkv", "ogv"]}
|
||||||
|
53
mediagoblin/static/css/audio.css
Normal file
53
mediagoblin/static/css/audio.css
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
.audio-spectrogram {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.playhead {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
background: rgba(134, 212, 177, 0.3);
|
||||||
|
border-right: thin solid #ffaa00;
|
||||||
|
height: 100%;
|
||||||
|
-webkit-transition: width .1s ease-out;
|
||||||
|
-moz-transition: width .1s ease-out;
|
||||||
|
}
|
||||||
|
.audio-control-play-pause {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
/* background: rgba(0, 0, 0, 0.7); */
|
||||||
|
font-size: 40px;
|
||||||
|
width: 50px;
|
||||||
|
text-shadow: 0 0 10px black;
|
||||||
|
}
|
||||||
|
.audio-control-play-pause.playing {
|
||||||
|
color: #b71500;
|
||||||
|
}
|
||||||
|
.audio-control-play-pause.paused {
|
||||||
|
color: rgb(134, 212, 177);
|
||||||
|
}
|
||||||
|
.buffered {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 2px;
|
||||||
|
width: 0;
|
||||||
|
-webkit-transition: width 1s ease-out;
|
||||||
|
-moz-transition: width 1s ease-out;
|
||||||
|
background: rgba(134, 177, 212, 1);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.seekbar {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.audio-currentTime {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
background: rgba(0, 0, 0, 0.7);
|
||||||
|
}
|
140
mediagoblin/static/js/audio.js
Normal file
140
mediagoblin/static/js/audio.js
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
/**
|
||||||
|
* GNU MediaGoblin -- federated, autonomous media hosting
|
||||||
|
* Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var audioPlayer = new Object();
|
||||||
|
|
||||||
|
(function (audioPlayer) {
|
||||||
|
audioPlayer.init = function (audioElement) {
|
||||||
|
audioPlayer.audioElement = audioElement;
|
||||||
|
console.log(audioElement);
|
||||||
|
attachEvents();
|
||||||
|
$(audioElement).hide();
|
||||||
|
};
|
||||||
|
|
||||||
|
function attachEvents () {
|
||||||
|
audioPlayer.audioElement.addEventListener('durationchange', audioPlayer.durationChange, true);
|
||||||
|
audioPlayer.audioElement.addEventListener('timeupdate', audioPlayer.timeUpdate, true);
|
||||||
|
audioPlayer.audioElement.addEventListener('progress', audioPlayer.onProgress, true);
|
||||||
|
$(document).ready( function () {
|
||||||
|
$('.audio-spectrogram').delegate('.seekbar', 'click', audioPlayer.onSeek);
|
||||||
|
$('.audio-spectrogram').delegate('.audio-control-play-pause', 'click', audioPlayer.playPause);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
audioPlayer.onProgress = function(a, b, c) {
|
||||||
|
console.log(a, b, c);
|
||||||
|
buffered = audioPlayer.audioElement.buffered;
|
||||||
|
|
||||||
|
ranges = new Array();
|
||||||
|
|
||||||
|
for (i = 0; i < buffered.length; i++) {
|
||||||
|
ranges[i] = new Array();
|
||||||
|
ranges[i][0] = buffered.start(i);
|
||||||
|
ranges[i][1] = buffered.end(i);
|
||||||
|
}
|
||||||
|
console.log('ranges', ranges);
|
||||||
|
$('.audio-spectrogram .buffered').width(
|
||||||
|
(ranges[0][1] / audioPlayer.audioElement.duration) * audioPlayer.imageElement.width());
|
||||||
|
};
|
||||||
|
|
||||||
|
audioPlayer.onSeek = function (e) {
|
||||||
|
console.log('onSeek', e);
|
||||||
|
im = audioPlayer.imageElement;
|
||||||
|
pos = e.offsetX / im.width();
|
||||||
|
audioPlayer.audioElement.currentTime = pos * audioPlayer.audioElement.duration;
|
||||||
|
audioPlayer.audioElement.play();
|
||||||
|
audioPlayer.setState(audioPlayer.PLAYING);
|
||||||
|
};
|
||||||
|
|
||||||
|
audioPlayer.playPause = function (e) {
|
||||||
|
console.log('playPause', e);
|
||||||
|
if (audioPlayer.audioElement.paused) {
|
||||||
|
audioPlayer.audioElement.play();
|
||||||
|
audioPlayer.setState(audioPlayer.PLAYING);
|
||||||
|
} else {
|
||||||
|
audioPlayer.audioElement.pause();
|
||||||
|
audioPlayer.setState(audioPlayer.PAUSED);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
audioPlayer.NULL = null;
|
||||||
|
audioPlayer.PLAYING = 2;
|
||||||
|
audioPlayer.PAUSED = 4;
|
||||||
|
|
||||||
|
audioPlayer.state = audioPlayer.NULL;
|
||||||
|
|
||||||
|
audioPlayer.setState = function (state) {
|
||||||
|
if (state == audioPlayer.state) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case audioPlayer.PLAYING:
|
||||||
|
$('.audio-spectrogram .audio-control-play-pause')
|
||||||
|
.removeClass('paused').addClass('playing')
|
||||||
|
.text('■');
|
||||||
|
break;
|
||||||
|
case audioPlayer.PAUSED:
|
||||||
|
$('.audio-spectrogram .audio-control-play-pause')
|
||||||
|
.removeClass('playing').addClass('paused')
|
||||||
|
.text('▶');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
audioPlayer.durationChange = function () {
|
||||||
|
duration = audioPlayer.audioElement.duration;
|
||||||
|
};
|
||||||
|
|
||||||
|
audioPlayer.timeUpdate = function () {
|
||||||
|
currentTime = audioPlayer.audioElement.currentTime;
|
||||||
|
playhead = audioPlayer.imageElement.parent().find('.playhead');
|
||||||
|
playhead.css('width', (currentTime / audioPlayer.audioElement.duration) * audioPlayer.imageElement.width());
|
||||||
|
time = formatTime(currentTime);
|
||||||
|
duration = formatTime(audioPlayer.audioElement.duration);
|
||||||
|
audioPlayer.imageElement.parent().find('.audio-currentTime').text(time + '/' + duration);
|
||||||
|
};
|
||||||
|
|
||||||
|
function formatTime(seconds) {
|
||||||
|
var h = Math.floor(seconds / (60 * 60));
|
||||||
|
var m = Math.floor((seconds - h * 60 * 60) / 60);
|
||||||
|
var s = Math.round(seconds - h * 60 * 60 - m * 60);
|
||||||
|
return '' + (h ? (h < 10 ? '0' + h : h) + ':' : '') + (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
|
||||||
|
}
|
||||||
|
|
||||||
|
audioPlayer.attachToImage = function (imageElement) {
|
||||||
|
/**
|
||||||
|
* Attach the player to an image element
|
||||||
|
*/
|
||||||
|
console.log(imageElement);
|
||||||
|
im = $(imageElement);
|
||||||
|
audioPlayer.imageElement = im;
|
||||||
|
$('<div class="playhead"></div>').appendTo(im.parent());
|
||||||
|
$('<div class="buffered"></div>').appendTo(im.parent());
|
||||||
|
$('<div class="seekbar"></div>').appendTo(im.parent());
|
||||||
|
$('<div class="audio-control-play-pause paused">▶</div>').appendTo(im.parent());
|
||||||
|
$('<div class="audio-currentTime">00:00</div>').appendTo(im.parent());
|
||||||
|
};
|
||||||
|
})(audioPlayer);
|
||||||
|
|
||||||
|
$(document).ready(function () {
|
||||||
|
audioElements = $('.audio-media .audio-player');
|
||||||
|
audioPlayer.init(audioElements[0]);
|
||||||
|
audioPlayer.attachToImage($('.audio-spectrogram img')[0]);
|
||||||
|
});
|
||||||
|
|
@ -18,6 +18,13 @@
|
|||||||
|
|
||||||
{% extends 'mediagoblin/user_pages/media.html' %}
|
{% extends 'mediagoblin/user_pages/media.html' %}
|
||||||
|
|
||||||
|
{% block mediagoblin_head %}
|
||||||
|
{{ super() }}
|
||||||
|
<link rel="stylesheet" type="text/css" href="{{ request.staticdirect('/css/audio.css') }}" />
|
||||||
|
<script type="text/javascript" src="{{ request.staticdirect(
|
||||||
|
'/js/audio.js') }}"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block mediagoblin_media %}
|
{% block mediagoblin_media %}
|
||||||
<div class="audio-media">
|
<div class="audio-media">
|
||||||
{% if 'spectrogram' in media.media_files %}
|
{% if 'spectrogram' in media.media_files %}
|
||||||
|
@ -219,6 +219,28 @@ class TestSubmission:
|
|||||||
request.db.MediaEntry.find(
|
request.db.MediaEntry.find(
|
||||||
{'_id': media._id}).count())
|
{'_id': media._id}).count())
|
||||||
|
|
||||||
|
def test_sniffing(self):
|
||||||
|
'''
|
||||||
|
Test sniffing mechanism to assert that regular uploads work as intended
|
||||||
|
'''
|
||||||
|
template.clear_test_template_context()
|
||||||
|
response = self.test_app.post(
|
||||||
|
'/submit/', {
|
||||||
|
'title': 'UNIQUE_TITLE_PLS_DONT_CREATE_OTHER_MEDIA_WITH_THIS_TITLE'
|
||||||
|
}, upload_files=[(
|
||||||
|
'file', GOOD_JPG)])
|
||||||
|
|
||||||
|
response.follow()
|
||||||
|
|
||||||
|
context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/user_pages/user.html']
|
||||||
|
|
||||||
|
request = context['request']
|
||||||
|
|
||||||
|
media = request.db.MediaEntry.find_one({
|
||||||
|
u'title': u'UNIQUE_TITLE_PLS_DONT_CREATE_OTHER_MEDIA_WITH_THIS_TITLE'})
|
||||||
|
|
||||||
|
assert media.media_type == 'mediagoblin.media_types.image'
|
||||||
|
|
||||||
def test_malicious_uploads(self):
|
def test_malicious_uploads(self):
|
||||||
# Test non-suppoerted file with non-supported extension
|
# Test non-suppoerted file with non-supported extension
|
||||||
# -----------------------------------------------------
|
# -----------------------------------------------------
|
||||||
|
Loading…
x
Reference in New Issue
Block a user