merging changes

This commit is contained in:
rolux 2011-08-23 08:08:59 +00:00
commit 8d7ed0280a
10 changed files with 175 additions and 49 deletions

View file

@ -133,6 +133,13 @@
"group": true, "group": true,
"sort": "person" "sort": "person"
}, },
{
"id": "parts",
"title": "Parts",
"type": "integer",
"columnWidth": 60,
"rightsLevel": 1
},
{ {
"id": "numberofactors", "id": "numberofactors",
"title": "Number of Actors", "title": "Number of Actors",
@ -561,6 +568,7 @@
}, },
"userLevels": ["guest", "member", "staff", "admin"], "userLevels": ["guest", "member", "staff", "admin"],
"video": { "video": {
"download": false,
"formats": ["webm", "mp4"], "formats": ["webm", "mp4"],
"resolutions": [96] "resolutions": [96]
} }

View file

@ -161,6 +161,7 @@ class File(models.Model):
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
if self.auto: if self.auto:
self.set_state() self.set_state()
self.available = self.streams.filter(source=None, available=True).count() > 0
super(File, self).save(*args, **kwargs) super(File, self).save(*args, **kwargs)
#upload and data handling #upload and data handling
@ -498,6 +499,7 @@ class Stream(models.Model):
resolution=resolution, format=f) resolution=resolution, format=f)
if created: if created:
derivative.source = self derivative.source = self
derivative.save()
name = derivative.name() name = derivative.name()
derivative.video.name = os.path.join(os.path.dirname(self.video.name), name) derivative.video.name = os.path.join(os.path.dirname(self.video.name), name)
derivative.encode() derivative.encode()
@ -528,6 +530,8 @@ class Stream(models.Model):
else: else:
self.aspect_ratio = 128/80 self.aspect_ratio = 128/80
super(Stream, self).save(*args, **kwargs) super(Stream, self).save(*args, **kwargs)
if self.available and not self.file.available:
self.file.save()
def json(self): def json(self):
if settings.XSENDFILE or settings.XACCELREDIRECT: if settings.XSENDFILE or settings.XACCELREDIRECT:

View file

@ -91,10 +91,11 @@ def update_files(user, volume, files):
@task(queue="encoding") @task(queue="encoding")
def process_stream(fileId): def process_stream(fileId):
file = models.Stream.objects.get(id=fileId) file = models.File.objects.get(id=fileId)
streams = file.streams.filter(source=None) streams = file.streams.filter(source=None)
if streams.count() >0: if streams.count() > 0:
stream = streams[0] stream = streams[0]
stream.make_timeline() stream.make_timeline()
stream.extract_derivatives() stream.extract_derivatives()
file.item.update_timeline()
return True return True

View file

@ -13,7 +13,7 @@ import unicodedata
from urllib import quote from urllib import quote
from django.db import models from django.db import models
from django.db.models import Sum, Count from django.db.models import Count, Q, Sum
from django.core.files.base import ContentFile from django.core.files.base import ContentFile
from django.utils import simplejson as json from django.utils import simplejson as json
from django.conf import settings from django.conf import settings
@ -30,14 +30,15 @@ import ox.image
import managers import managers
import utils import utils
import tasks import tasks
from archive import extract from .timelines import join_timelines
from archive import extract
from annotation.models import Annotation, Layer from annotation.models import Annotation, Layer
from person.models import get_name_sort from person.models import get_name_sort
from app.models import site_config from app.models import site_config
def get_item(info, user=None): def get_item(info, user=None, async=False):
''' '''
info dict with: info dict with:
imdbId, title, director, episode_title, season, series imdbId, title, director, episode_title, season, series
@ -56,7 +57,10 @@ def get_item(info, user=None):
} }
item.user = user item.user = user
item.save() item.save()
tasks.update_external.delay(item.itemId) if async:
tasks.update_external.delay(item.itemId)
else:
item.update_external()
else: else:
q = Item.objects.all() q = Item.objects.all()
for key in ('title', 'director', 'year'): for key in ('title', 'director', 'year'):
@ -789,17 +793,23 @@ class Item(models.Model):
self.save() self.save()
def streams(self): def streams(self):
return [video.streams.filter(source=None)[0] for video in self.main_videos()] return [video.streams.filter(source=None, available=True)[0]
for video in self.main_videos()]
def update_timeline(self, force=False): def update_timeline(self, force=False):
config = site_config()
streams = self.streams() streams = self.streams()
self.make_timeline() self.make_timeline()
self.data['cuts'] = extract.cuts(self.timeline_prefix) self.data['cuts'] = extract.cuts(self.timeline_prefix)
self.data['color'] = extract.average_color(self.timeline_prefix) self.data['color'] = extract.average_color(self.timeline_prefix)
#extract.timeline_strip(self, self.data['cuts'], stream.info, self.timeline_prefix[:-8]) #extract.timeline_strip(self, self.data['cuts'], stream.info, self.timeline_prefix[:-8])
self.select_frame()
self.make_local_poster() self.make_local_poster()
self.make_poster() self.make_poster()
self.make_icon() self.make_icon()
if config['video']['download']:
self.make_torrent()
self.load_subtitles()
self.rendered = streams != [] self.rendered = streams != []
self.save() self.save()
@ -855,7 +865,8 @@ class Item(models.Model):
def make_timeline(self): def make_timeline(self):
streams = self.streams() streams = self.streams()
if len(streams) > 1: if len(streams) > 1:
print "FIXME, needs to build timeline from parts" timelines = [s.timeline_prefix for s in self.streams()]
join_timelines(timelines, self.timeline_prefix)
def make_poster(self, force=False): def make_poster(self, force=False):
if not self.poster or force: if not self.poster or force:
@ -960,6 +971,43 @@ class Item(models.Model):
os.unlink(f) os.unlink(f)
return icon return icon
def load_subtitles(self):
layer = Layer.objects.get(name='subtitles')
Annotation.objects.filter(layer=layer,item=self).delete()
offset = 0
language = ''
languages = [f.language for f in self.files.filter(is_main=True, is_subtitle=True,
available=True)]
if languages:
if 'en' in languages:
language = 'en'
elif '' in languages:
language = ''
else:
language = languages[0]
for f in self.files.filter(is_main=True, is_subtitle=True,
available=True, language=language).order_by('part'):
user = f.instances.all()[0].volume.user
for data in f.srt(offset):
annotation = Annotation(
item=f.item,
layer=layer,
start=data['in'],
end=data['out'],
value=data['value'],
user=user
)
annotation.save()
duration = self.files.filter(Q(is_audio=True)|Q(is_video=True)) \
.filter(is_main=True, available=True, part=f.part)
if duration:
duration = duration[0].duration
else:
Annotation.objects.filter(layer=layer,item=self).delete()
break
offset += duration
self.update_find()
def delete_item(sender, **kwargs): def delete_item(sender, **kwargs):
i = kwargs['instance'] i = kwargs['instance']
i.delete_files() i.delete_files()

View file

@ -3,7 +3,6 @@
from datetime import timedelta from datetime import timedelta
from celery.decorators import task, periodic_task from celery.decorators import task, periodic_task
from django.db.models import Q
import models import models
@ -32,39 +31,5 @@ def update_timeline(itemId):
def load_subtitles(itemId): def load_subtitles(itemId):
item = models.Item.objects.get(itemId=itemId) item = models.Item.objects.get(itemId=itemId)
layer = models.Layer.objects.get(name='subtitles') item.load_subtitles()
models.Annotation.objects.filter(layer=layer,item=item).delete()
offset = 0
language = ''
languages = [f.language for f in item.files.filter(is_main=True, is_subtitle=True,
available=True)]
if languages:
if 'en' in languages:
language = 'en'
elif '' in languages:
language = ''
else:
language = languages[0]
for f in item.files.filter(is_main=True, is_subtitle=True,
available=True, language=language).order_by('part'):
user = f.instances.all()[0].volume.user
for data in f.srt(offset):
annotation = models.Annotation(
item=f.item,
layer=layer,
start=data['in'],
end=data['out'],
value=data['value'],
user=user
)
annotation.save()
duration = item.files.filter(Q(is_audio=True)|Q(is_video=True)) \
.filter(is_main=True, available=True, part=f.part)
if duration:
duration = duration[0].duration
else:
models.Annotation.objects.filter(layer=layer,item=item).delete()
break
offset += duration
item.update_find()

101
pandora/item/timelines.py Normal file
View file

@ -0,0 +1,101 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division, with_statement
from glob import glob
import Image
def loadTimeline(timeline_prefix, height=64):
files = sorted(glob('%s.%s.*.png' % (timeline_prefix, height)))
f = Image.open(files[0])
width = f.size[0]
f = Image.open(files[-1])
duration = f.size[0] + (len(files)-1)*width
timeline = Image.new("RGB", (duration, height))
pos = 0
for f in files:
part = Image.open(f)
timeline.paste(part, (pos, 0, pos + part.size[0], height))
pos += part.size[0]
return timeline
def makeTiles(timeline_prefix, height=16, width=3600):
files = glob('%s.64.*.png' % timeline_prefix)
fps = 25
part_step = 60
output_width = width
width = len(files) * part_step
timeline = Image.new("RGB", (width, height))
pos = 0
for f in sorted(files):
part = Image.open(f)
part_width = int(part.size[0] / fps)
part = part.resize((part_width, height), Image.ANTIALIAS)
timeline.paste(part, (pos, 0, pos+part_width, height))
pos += part_width
timeline = timeline.crop((0, 0, pos, height))
pos = 0
i = 0
while pos < timeline.size[0]:
end = min(pos+output_width, timeline.size[0])
timeline.crop((pos, 0, end, timeline.size[1])).save('%s.%s.%04d.png' % (timeline_prefix, timeline.size[1], i))
pos += output_width
i += 1
def makeTimelineOverview(timeline_prefix, width, inpoint=0, outpoint=0, duration=-1, height=16):
input_scale = 25
timeline_file = '%s.%s.png' % (timeline_prefix, height)
if outpoint > 0:
timeline_file = '%s.overview.%s.%d-%d.png' % (timeline_prefix, height, inpoint, outpoint)
timeline = loadTimeline(timeline_prefix)
duration = timeline.size[0]
if inpoint<=0:
inpoint = 0
else:
inpoint = inpoint * input_scale
if outpoint<=0:
outpoint = duration
else:
outpoint = outpoint * input_scale
timeline = timeline.crop((inpoint, 0, outpoint, timeline.size[1])).resize((width, height), Image.ANTIALIAS)
timeline.save(timeline_file)
def join_timelines(timelines, prefix):
height = 64
width = 1500
tiles = []
for timeline in timelines:
tiles += sorted(glob('%s.%s.*.png'%(timeline, height)))
tiles = map(Image.open, tiles)
duration = sum(map(lambda i: i.size[0], tiles))
timeline = Image.new("RGB", (duration, height))
pos = 0
for tile in tiles:
timeline.paste(tile, (pos, 0, pos+tile.size[0], height))
pos += tile.size[0]
pos = 0
i = 0
while pos < timeline.size[0]:
end = min(pos+width, timeline.size[0])
timeline_name = '%s.%s.%04d.png' % (prefix, timeline.size[1], i)
timeline.crop((pos, 0, end, timeline.size[1])).save(timeline_name)
pos += width
i += 1
makeTiles(prefix, 16, 3600)
makeTimelineOverview(prefix, 1920, height=16)
makeTimelineOverview(prefix, 1920, height=64)

View file

@ -446,7 +446,8 @@
}, },
"userLevels": ["guest", "member", "staff", "admin"], "userLevels": ["guest", "member", "staff", "admin"],
"video": { "video": {
"formats": ["webm", "h264"], "download": true,
"formats": ["webm", "mp4"],
"resolutions": [480, 240, 96] "resolutions": [480, 240, 96]
} }
} }

View file

@ -1 +0,0 @@
js/jquery/

File diff suppressed because one or more lines are too long

View file

@ -502,7 +502,7 @@ pandora.ui.infoView = function(data) {
$reflectionIcon.attr({src: src}); $reflectionIcon.attr({src: src});
iconSize = iconSize == 256 ? 512 : 256; iconSize = iconSize == 256 ? 512 : 256;
iconRatio = pandora.user.ui.icons == 'posters' iconRatio = pandora.user.ui.icons == 'posters'
? data.poster.width / data.poster.height : 1; ? data.posterRatio : 1;
toggleIconSize(); toggleIconSize();
pandora.user.level == 'admin' && $list.replaceWith($list = renderList()); pandora.user.level == 'admin' && $list.replaceWith($list = renderList());
}; };
@ -515,4 +515,4 @@ pandora.ui.infoView = function(data) {
return that; return that;
} }