This commit is contained in:
rolux 2011-10-29 16:58:47 +00:00
commit c6f11433f9
7 changed files with 159 additions and 111 deletions

View file

@ -109,12 +109,13 @@ class Annotation(models.Model):
return self.value return self.value
def set_public_id(self): def set_public_id(self):
public_id = Annotation.objects.filter(item=self.item, id__lt=self.id).count() if self.id:
self.public_id = "%s/%s" % (self.item.itemId, ox.to26(public_id)) public_id = Annotation.objects.filter(item=self.item, id__lt=self.id).count()
Annotation.objects.filter(id=self.id).update(public_id=self.public_id) self.public_id = "%s/%s" % (self.item.itemId, ox.to26(public_id))
Annotation.objects.filter(id=self.id).update(public_id=self.public_id)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
set_public_id = not self.id set_public_id = not self.id or not self.public_id
#no clip or update clip #no clip or update clip
if not self.clip and not self.layer.private or \ if not self.clip and not self.layer.private or \
@ -160,5 +161,5 @@ class Annotation(models.Model):
return j return j
def __unicode__(self): def __unicode__(self):
return u"%s/%s-%s" %(self.item, self.start, self.end) return u"%s %s-%s" %(self.public_id, self.start, self.end)

View file

@ -294,11 +294,12 @@ def average_color(prefix, start=0, end=0):
timelines = sorted(filter(lambda t: t!= '%s%sp.png'%(prefix,height), glob("%s%sp*.png"%(prefix, height)))) timelines = sorted(filter(lambda t: t!= '%s%sp.png'%(prefix,height), glob("%s%sp*.png"%(prefix, height))))
for image in timelines: for image in timelines:
start_offset = 0 start_offset = 0
timeline = Image.open(image).convert('RGB') if start and frames + 1500 < start:
frames += timeline.size[0] frames += 1500
if start and frames < start:
continue continue
elif start and frames > start > frames-timeline.size[0]: timeline = Image.open(image)
frames += timeline.size[0]
if start and frames > start > frames-timeline.size[0]:
start_offset = start - (frames-timeline.size[0]) start_offset = start - (frames-timeline.size[0])
box = (start_offset, 0, timeline.size[0], height) box = (start_offset, 0, timeline.size[0], height)
timeline = timeline.crop(box) timeline = timeline.crop(box)
@ -307,7 +308,7 @@ def average_color(prefix, start=0, end=0):
box = (0, 0, end_offset, height) box = (0, 0, end_offset, height)
timeline = timeline.crop(box) timeline = timeline.crop(box)
p = np.asarray(timeline, dtype=np.float32) p = np.asarray(timeline.convert('RGB'), dtype=np.float32)
p = np.sum(p, axis=0) / height #average color per frame p = np.sum(p, axis=0) / height #average color per frame
pixels.append(p) pixels.append(p)

View file

@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from optparse import make_option
import os
from os.path import join, dirname, basename, splitext, exists
from django.core.management.base import BaseCommand, CommandError
from django.conf import settings
import monkey_patch.models
from ... import models
class Command(BaseCommand):
"""
rebuild sort/search cache for all items.
"""
help = 'listen to rabbitmq and execute encoding tasks.'
args = ''
option_list = BaseCommand.option_list + (
make_option('--all', action='store_true', dest='all',
default=False, help='update all items, otherwise oldes N'),
make_option('-n', '--items', action='store', dest='items', type=int,
default=30, help='number of items ot update'),
)
def handle(self, **options):
offset = 0
chunk = options['all'] and 100 or options['items']
count = pos = models.Item.objects.count()
while options['all'] and offset <= count or offset < options['items']:
for i in models.Item.objects.all().order_by('modified')[offset:offset+chunk]:
print pos, i.itemId, i.modified
i.update_external()
pos -= 1
offset += chunk

View file

@ -13,7 +13,7 @@ import uuid
import unicodedata import unicodedata
from urllib import quote from urllib import quote
from django.db import models from django.db import models, transaction
from django.db.models import Count, Q, Sum from django.db.models import Count, Q, Sum
from django.core.files.base import ContentFile from django.core.files.base import ContentFile
from django.conf import settings from django.conf import settings
@ -340,6 +340,8 @@ class Item(models.Model):
#FIXME: should this really happen for annotations? #FIXME: should this really happen for annotations?
for a in self.annotations.all(): for a in self.annotations.all():
a.item = other a.item = other
a.public_id = None
a.save()
if hasattr(self, 'files'): if hasattr(self, 'files'):
for f in self.files.all(): for f in self.files.all():
@ -516,45 +518,46 @@ class Item(models.Model):
else: else:
ItemFind.objects.filter(item=self, key=key).delete() ItemFind.objects.filter(item=self, key=key).delete()
for key in settings.CONFIG['itemKeys']: with transaction.commit_on_success():
i = key['id'] for key in settings.CONFIG['itemKeys']:
if i == 'title': i = key['id']
save(i, u'\n'.join([self.get('title', 'Untitled'), if i == 'title':
self.get('originalTitle', '')])) save(i, u'\n'.join([self.get('title', 'Untitled'),
elif i == 'rightslevel': self.get('originalTitle', '')]))
save(i, self.level) elif i == 'rightslevel':
elif i == 'filename': save(i, self.level)
save(i, elif i == 'filename':
'\n'.join([f.path for f in self.files.all()])) save(i,
elif key['type'] == 'layer': '\n'.join([f.path for f in self.files.all()]))
qs = Annotation.objects.filter(layer__name=i, item=self).order_by('start') elif key['type'] == 'layer':
save(i, '\n'.join([l.value for l in qs])) qs = Annotation.objects.filter(layer__name=i, item=self).order_by('start')
elif i != '*' and i not in self.facet_keys: save(i, '\n'.join([l.value for l in qs]))
value = self.get(i) elif i != '*' and i not in self.facet_keys:
if isinstance(value, list): value = self.get(i)
value = u'\n'.join(value) if isinstance(value, list):
save(i, value) value = u'\n'.join(value)
save(i, value)
for key in self.facet_keys: for key in self.facet_keys:
if key == 'character': if key == 'character':
values = self.get('cast', '') values = self.get('cast', '')
if values: if values:
values = filter(lambda x: x.strip(), values = filter(lambda x: x.strip(),
[f['character'] for f in values]) [f['character'] for f in values])
values = list(set(values))
elif key == 'name':
values = []
for k in map(lambda x: x['id'],
filter(lambda x: x.get('sort') == 'person',
settings.CONFIG['itemKeys'])):
values += self.get(k, [])
values = list(set(values)) values = list(set(values))
elif key == 'name': else:
values = [] values = self.get(key, '')
for k in map(lambda x: x['id'], if isinstance(values, list):
filter(lambda x: x.get('sort') == 'person', save(key, '\n'.join(values))
settings.CONFIG['itemKeys'])): else:
values += self.get(k, []) save(key, values)
values = list(set(values))
else:
values = self.get(key, '')
if isinstance(values, list):
save(key, '\n'.join(values))
else:
save(key, values)
def update_sort(self): def update_sort(self):
try: try:
@ -933,7 +936,7 @@ class Item(models.Model):
def make_timeline(self): def make_timeline(self):
streams = self.streams() streams = self.streams()
if len(streams) > 1: if streams.count() > 1:
timelines = [s.timeline_prefix for s in self.streams()] timelines = [s.timeline_prefix for s in self.streams()]
join_timelines(timelines, self.timeline_prefix) join_timelines(timelines, self.timeline_prefix)
@ -1041,61 +1044,63 @@ class Item(models.Model):
return icon return icon
def load_subtitles(self): def load_subtitles(self):
layer = Layer.objects.get(name='subtitles') with transaction.commit_on_success():
Annotation.objects.filter(layer=layer,item=self).delete() layer = Layer.objects.get(name='subtitles')
offset = 0 Annotation.objects.filter(layer=layer,item=self).delete()
language = '' offset = 0
subtitles = self.files.filter(selected=True, is_subtitle=True, available=True) language = ''
languages = [f.language for f in subtitles] subtitles = self.files.filter(selected=True, is_subtitle=True, available=True)
if languages: languages = [f.language for f in subtitles]
if 'en' in languages: if languages:
language = 'en' if 'en' in languages:
elif '' in languages: language = 'en'
language = '' elif '' in languages:
else: language = ''
language = languages[0] else:
language = languages[0]
#loop over all videos #loop over all videos
for f in self.files.filter(Q(is_audio=True)|Q(is_video=True)) \ for f in self.files.filter(Q(is_audio=True)|Q(is_video=True)) \
.filter(selected=True).order_by('part'): .filter(selected=True).order_by('part'):
subtitles_added = False subtitles_added = False
prefix = os.path.splitext(f.path)[0] prefix = os.path.splitext(f.path)[0]
if f.instances.all().count() > 0: if f.instances.all().count() > 0:
user = f.instances.all()[0].volume.user user = f.instances.all()[0].volume.user
else: else:
#FIXME: allow annotations from no user instead? #FIXME: allow annotations from no user instead?
user = User.objects.all().order_by('id')[0] user = User.objects.all().order_by('id')[0]
#if there is a subtitle with the same prefix, import #if there is a subtitle with the same prefix, import
q = subtitles.filter(path__startswith=prefix, q = subtitles.filter(path__startswith=prefix,
language=language) language=language)
if q.count() == 1: if q.count() == 1:
s = q[0] s = q[0]
for data in s.srt(offset): for data in s.srt(offset):
subtitles_added = True subtitles_added = True
annotation = Annotation( annotation = Annotation(
item=self, item=self,
layer=layer, layer=layer,
start=data['in'], start=data['in'],
end=data['out'], end=data['out'],
value=data['value'], value=data['value'],
user=user user=user
) )
annotation.save() annotation.save()
#otherwise add empty 5 seconds annotation every minute #otherwise add empty 5 seconds annotation every minute
if not subtitles_added: if not subtitles_added:
for i in range(int (offset / 60) * 60 + 60, start = offset and int (offset / 60) * 60 + 60 or 0
int(offset + f.duration) - 5, for i in range(start,
60): int(offset + f.duration) - 5,
annotation = Annotation( 60):
item=self, annotation = Annotation(
layer=layer, item=self,
start=i, layer=layer,
end=i + 5, start=i,
value='', end=i + 5,
user=user value='',
) user=user
annotation.save() )
offset += f.duration annotation.save()
offset += f.duration
self.update_find() self.update_find()
def delete_item(sender, **kwargs): def delete_item(sender, **kwargs):

View file

@ -154,8 +154,9 @@ pandora.ui.clipList = function(videoRatio) {
poster: '/' + item + '/' + height + 'p' + points[0] + '.jpg', poster: '/' + item + '/' + height + 'p' + points[0] + '.jpg',
rewind: true, rewind: true,
video: partsAndPoints.parts.map(function(i) { video: partsAndPoints.parts.map(function(i) {
return '/' + item + '/96p' + (i + 1) var part = (i + 1),
+ '.' + pandora.user.videoFormat; prefix = pandora.site.site.videoprefix.replace('PART', part);
return prefix + '/' + item + '/96p' + part + '.' + pandora.user.videoFormat;
}), }),
width: width width: width
}) })

View file

@ -35,17 +35,19 @@ pandora.ui.clipPlayer = function() {
length = range[1] - range[0], length = range[1] - range[0],
data = []; data = [];
result.data.items.forEach(function(item, i) { result.data.items.forEach(function(item, i) {
var id = item.id.split('/')[0] var id = item.id.split('/')[0];
pandora.api.get({id: id, keys: ['durations']}, function(result) { pandora.api.get({id: id, keys: ['durations']}, function(result) {
//Ox.print('API get item', id, 'result', result.data); //Ox.print('API get item', id, 'result', result.data);
var points = [item['in'], item.out], var points = [item['in'], item.out],
partsAndPoints = pandora.getVideoPartsAndPoints(result.data.durations, points); partsAndPoints = pandora.getVideoPartsAndPoints(result.data.durations, points);
data[i] = { data[i] = {
parts: partsAndPoints.parts.map(function(i) { parts: partsAndPoints.parts.map(function(i) {
return '/' + id + '/96p' + (i + 1) + '.' + pandora.user.videoFormat; var part = (i + 1),
prefix = pandora.site.site.videoprefix.replace('PART', part);
return prefix + '/' + id + '/96p' + part + '.' + pandora.user.videoFormat;
}), }),
points: partsAndPoints.points points: partsAndPoints.points
} };
if (++counter == length) { if (++counter == length) {
callback(data); callback(data);
} }

View file

@ -91,8 +91,9 @@ pandora.ui.itemClips = function(options) {
poster: '/' + self.options.id + '/' + self.height + 'p' + points[0] + '.jpg', poster: '/' + self.options.id + '/' + self.height + 'p' + points[0] + '.jpg',
rewind: true, rewind: true,
video: partsAndPoints.parts.map(function(i) { video: partsAndPoints.parts.map(function(i) {
return '/' + self.options.id + '/96p' + (i + 1) var part = (i + 1),
+ '.' + pandora.user.videoFormat; prefix = pandora.site.site.videoprefix.replace('PART', part);
return prefix + '/' + self.options.id + '/96p' + part + '.' + pandora.user.videoFormat;
}), }),
width: self.width width: self.width
}) })