thumbnail generation and primitive search

git-svn-id: http://yolanda.mister-muffin.de/svn@405 7eef14d0-6ed0-489d-bf55-20463b2d70db
This commit is contained in:
erlehmann 2008-12-04 06:44:28 +00:00
parent 2003134084
commit 76ad4c8710
9 changed files with 78 additions and 47 deletions

View file

@ -19,9 +19,13 @@ port = 5000
use = egg:Yolanda use = egg:Yolanda
full_stack = true full_stack = true
cache_dir = /tmp/yolanda/data cache_dir = /tmp/yolanda/data
beaker.session.key = yolanda beaker.session.key = yolandav
beaker.session.secret = somesecret beaker.session.secret = somesecret
directory_videos = videos
directory_video-stills = video-stills
directory_video-thumbnails = thumbnails
# If you'd like to fine-tune the individual locations of the cache data dirs # If you'd like to fine-tune the individual locations of the cache data dirs
# for the Cache data, or the Session saves, un-comment the desired settings # for the Cache data, or the Session saves, un-comment the desired settings
# here: # here:
@ -33,7 +37,6 @@ beaker.session.secret = somesecret
# execute malicious code after an exception is raised. # execute malicious code after an exception is raised.
#set debug = false #set debug = false
# Logging configuration # Logging configuration
[loggers] [loggers]
keys = root, yolanda keys = root, yolanda

View file

@ -32,14 +32,14 @@ def make_map():
video = kargs.pop('video') video = kargs.pop('video')
kargs['id'] = video['id'] kargs['id'] = video['id']
kargs['title'] = video['title'] kargs['dc_title'] = video['dc_title']
return kargs return kargs
map.connect('video_page', 'video/:id/:title', controller='video', _filter=video_expand) map.connect('video_page', 'video/:id/:dc_title', controller='video', _filter=video_expand)
# map.connect('video_file', 'video/:id.ogv', controller='video', action='file' _filter=video_expand) # map.connect('video_file', 'video/:id.ogv', controller='video', action='file' _filter=video_expand)
map.connect('download_page', 'download/:id/:title', controller='download', action="download") map.connect('download_page', 'download/:id/:dc_title', controller='download', action="download")
# everything else # everything else
map.connect(':controller/:action/:id') map.connect(':controller/:action/:id')

View file

@ -1,4 +1,21 @@
## Yolanda, a video CMS for the web
## Copyright (C) 2007, 2008 Nils Dagsson Moskopp, Johannes Schauer
## 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/>.
import logging import logging
import os
from yolanda.lib.base import * from yolanda.lib.base import *
@ -10,21 +27,27 @@ class SearchController(BaseController):
c.query = request.params['query'] c.query = request.params['query']
# c.results dummy raw_results = model.Video.query.filter_by(dc_title=c.query).all()
c.results = [
{'title': 'foobar', 'id': '23' }, if not raw_results:
{'title': 'blablupp', 'id': '42'}, c.message = {
{'title': 'uiae nrdt', 'id': '555'}, 'type': 'warning'
{'title': 'uiaenrtd uiaenrtd uiaenrdt', 'id': '666666666'}, }
{'title': 'foobar', 'id': '23'}, c.message['text']='No results for query "%s".' % c.query
{'title': 'blablupp', 'id': '42'}, return render('/xhtml/results.mako')
{'title': 'James Bond drives a bulletproof Aston Martin !!!', 'id': '555'},
{'title': 'uiaenrtd uiaenrtd uiaenrdt uiaenrtd uiaenrtd', 'id': '666666666'}, c.results = []
{'title': 'foobar', 'id': '123'},
{'title': 'blablupp', 'id': '42'}, for result in raw_results:
{'title': 'lolwtf hax !!!11', 'id': '9001'} c.results.append(
] {
'dc_title': result.dc_title,
'id': result.id,
'snapshot': os.path.join(config['directory_video-stills'],str(result.id)),
'thumbnail': os.path.join(config['directory_video-thumbnails'],str(result.id))
}
)
return render('/xhtml/results.mako') return render('/xhtml/results.mako')
# return request.params['query'] # return request.params['query']
# return h.form(h.url(action='search'), method='get') # return h.form(h.url(action='search'), method='get'

View file

@ -1,4 +1,4 @@
## <one line to give the program's name and a brief idea of what it does.> ## Yolanda, a video CMS for the web
## Copyright (C) 2007, 2008 Nils Dagsson Moskopp, Johannes Schauer ## Copyright (C) 2007, 2008 Nils Dagsson Moskopp, Johannes Schauer
## This program is free software: you can redistribute it and/or modify ## This program is free software: you can redistribute it and/or modify
@ -70,23 +70,25 @@ class UploadController(BaseController):
# TODO: enable several contributors # TODO: enable several contributors
dc_contributor = '', dc_contributor = '',
dc_created = '', # TODO: insert real data
dc_valid = '', dc_created = datetime(9999,9,9).strftime("%Y-%m-%d %H:%M:%S"),
dc_available = '', dc_valid = datetime(9999,9,9).strftime("%Y-%m-%d %H:%M:%S"),
dc_issued = '', dc_available = datetime(9999,9,9).strftime("%Y-%m-%d %H:%M:%S"),
dc_modified = '', dc_issued = datetime(9999,9,9).strftime("%Y-%m-%d %H:%M:%S"),
dc_dateAccepted = '', dc_modified = datetime(9999,9,9).strftime("%Y-%m-%d %H:%M:%S"),
dc_dateCopyrighted = '', dc_dateAccepted = datetime(9999,9,9).strftime("%Y-%m-%d %H:%M:%S"),
dc_dateSubmitted = datetime.today().isoformat(), dc_dateCopyrighted = datetime(9999,9,9).strftime("%Y-%m-%d %H:%M:%S"),
dc_dateSubmitted = datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
dc_identifier = '', dc_identifier = '',
dc_source = '', dc_source = '',
dc_language = request.params['language'], dc_language = request.params['language'],
dc_extent = timedelta(0), # TODO: insert videolength # TODO: insert videolength
dc_extent = timedelta(0),
dc_spatial = request.params['spatial'], dc_spatial = request.params['spatial'],
dc_temporal = request.params['temporal'], dc_temporal = datetime(9999,9,9).strftime("%Y-%m-%d %H:%M:%S"),
dc_rightsHolder = '', dc_rightsHolder = '',
@ -108,11 +110,12 @@ class UploadController(BaseController):
# define stuff # define stuff
videosource=os.path.join(config['cache.dir'], str(video.id)) videosource=os.path.join(config['cache.dir'], str(video.id))
videodestination=os.path.join(config['pylons.paths']['static_files'], "videos", str(video.id)) videodestination=os.path.join(config['pylons.paths']['static_files'], config['directory_videos'], str(video.id))
imagedestination=os.path.join(config['pylons.paths']['static_files'], "video-stills", str(video.id)) snapshotdestination=os.path.join(config['pylons.paths']['static_files'], config['directory_video-stills'], str(video.id))
thumbnaildestination=os.path.join(config['pylons.paths']['static_files'], config['directory_video-thumbnails'], str(video.id))
# start encoding thread in background # start encoding thread in background
threading.Thread(target=self.bgencode, args=(videosource, videodestination, imagedestination)).start() threading.Thread(target=self.bgencode, args=(videosource, videodestination, snapshotdestination, thumbnaildestination)).start()
# return 'Successfully uploaded: %s'%video.query.all() # return 'Successfully uploaded: %s'%video.query.all()
c.message = { c.message = {
@ -122,9 +125,11 @@ class UploadController(BaseController):
c.message['text']='Your file was successfully uploaded to "%s".'%videodestination c.message['text']='Your file was successfully uploaded to "%s".'%videodestination
return render('/xhtml/index.mako') return render('/xhtml/index.mako')
def bgencode(self, source, destination, snapshotdestination): def bgencode(self, source, destination, snapshotdestination, thumbnaildestination):
videosnapshot = snapshot.Snapshot(source).get_snapshot() videosnapshot = snapshot.Snapshot(source).get_snapshot()
videosnapshot.save(snapshotdestination, "JPEG") videosnapshot.save(snapshotdestination, 'JPEG')
videosnapshot.thumbnail((300,150))
videosnapshot.save(thumbnaildestination, 'JPEG')
videoencode = encode.Encode(source,destination) videoencode = encode.Encode(source,destination)
videoencode.run() videoencode.run()
os.unlink(source) os.unlink(source)

View file

@ -55,10 +55,9 @@ class Snapshot:
#get current buffer's capabilities #get current buffer's capabilities
caps = buffer.get_caps () caps = buffer.get_caps ()
#we are interested in it's dimension #we are interested in it's dimension
h, w = caps[0]['height'], caps[0]['width'] height, width = caps[0]['height'], caps[0]['width']
#using PIL we grab the image in raw RGB mode from the buffer data #using PIL we grab the image in raw RGB mode from the buffer data
im = Image.frombuffer('RGB', (w, h), buffer.data, im = Image.frombuffer('RGB', (width, height), buffer.data,'raw', 'RGB', 0, 1)
'raw', 'RGB', 0, 1)
#here we check the standard variance of a grayscale version of the #here we check the standard variance of a grayscale version of the
#current frame against the BORING_IMAGE_VARIANCE #current frame against the BORING_IMAGE_VARIANCE
if ImageStat.Stat(ImageOps.grayscale(im)).var[0] > \ if ImageStat.Stat(ImageOps.grayscale(im)).var[0] > \

View file

@ -6,4 +6,4 @@ available to Controllers. This module is available to both as 'h'.
from webhelpers import * from webhelpers import *
# between 0.9.6 and 0.9.7, some things are no longer imported by default # between 0.9.6 and 0.9.7, some things are no longer imported by default
from routes import url_for from pylons.controllers.util import url_for

View file

@ -23,8 +23,8 @@ class Video(Entity):
dc_dateCopyrighted = Field(DateTime) dc_dateCopyrighted = Field(DateTime)
dc_dateSubmitted = Field(DateTime) dc_dateSubmitted = Field(DateTime)
dc_identifier = Field(Unicode(255)) dc_identifier = Field(Unicode(255)) # URI
dc_source = Field(Unicode(255)) dc_source = Field(Unicode(255)) # URI
dc_language = Field(Unicode(3)) # see ISO 639-3 dc_language = Field(Unicode(3)) # see ISO 639-3
dc_extent = Field(Interval) dc_extent = Field(Interval)

View file

@ -8,7 +8,7 @@
<h1>Search</h1> <h1>Search</h1>
<form action="(h.url_for('search_results'))}" method="get"> <form action="${h.url_for('search_results')}" method="get">
<input id="query" name="query" type="text"/> <input id="query" name="query" type="text"/>
<input type="submit" value="Search"/> <input type="submit" value="Search"/>

View file

@ -5,7 +5,7 @@
</%def> </%def>
<%def name="heading()"> <%def name="heading()">
There are over 9000 videos matching "${c.query}". There are ${len(c.results)} videos matching "${c.query}".
</%def> </%def>
<%def name="results_listing(results)"> <%def name="results_listing(results)">
@ -13,11 +13,12 @@
% for result in c.results: % for result in c.results:
<li> <li>
<a href="${h.url_for('video_page', video=result)}"> <a href="${h.url_for('video_page', video=result)}">
<img src="${h.url_for('/images/404.png')}" alt='thumbnail for "${result['title']}"'/>
<img src="${result['thumbnail']}" alt='thumbnail for "${result['dc_title']}"'/>
</a> </a>
<br /> <br />
<a href="${h.url_for('video_page', video=result)}" class="title"> <a href="${h.url_for('video_page', video=result)}" class="title">
${result['title']} ${result['dc_title']}
</a> </a>
</li> </li>
% endfor % endfor