forked from 0x2620/pandora
cleanup file locations
This commit is contained in:
parent
38395eeed9
commit
8aa1f119ea
9 changed files with 254 additions and 100 deletions
|
@ -298,7 +298,7 @@ def divide(num, by):
|
||||||
arr = []
|
arr = []
|
||||||
div = int(num / by)
|
div = int(num / by)
|
||||||
mod = num % by
|
mod = num % by
|
||||||
for i in range(by):
|
for i in range(int(by)):
|
||||||
arr.append(div + (i > by - 1 - mod))
|
arr.append(div + (i > by - 1 - mod))
|
||||||
return arr
|
return arr
|
||||||
|
|
||||||
|
@ -313,7 +313,7 @@ def timeline_strip(movie, cuts, info, prefix):
|
||||||
timeline_height = 64
|
timeline_height = 64
|
||||||
timeline_width = 1500
|
timeline_width = 1500
|
||||||
fps = 25
|
fps = 25
|
||||||
frames = duration * fps
|
frames = int(duration * fps)
|
||||||
if cuts[0] != 0:
|
if cuts[0] != 0:
|
||||||
cuts.insert(0, 0)
|
cuts.insert(0, 0)
|
||||||
|
|
||||||
|
@ -327,31 +327,33 @@ def timeline_strip(movie, cuts, info, prefix):
|
||||||
timeline_image = Image.new('RGB', (timeline_width, timeline_height))
|
timeline_image = Image.new('RGB', (timeline_width, timeline_height))
|
||||||
if frame in cuts:
|
if frame in cuts:
|
||||||
c = cuts.index(frame)
|
c = cuts.index(frame)
|
||||||
duration = cuts[c + 1] - cuts[c]
|
if c +1 < len(cuts):
|
||||||
stills = math.ceil(duration / (video_width * timeline_height / video_height))
|
duration = cuts[c + 1] - cuts[c]
|
||||||
widths = divide(duration, stills)
|
stills = math.ceil(duration / (video_width * timeline_height / video_height))
|
||||||
still = frame
|
widths = divide(duration, stills)
|
||||||
if _debug:
|
still = frame
|
||||||
print widths, duration, stills, cuts[c], cuts[c + 1]
|
|
||||||
for s in range(int(stills)):
|
|
||||||
still_ratio = widths[s] / timeline_height
|
|
||||||
if video_ratio > still_ratio:
|
|
||||||
width = int(round(video_height * still_ratio))
|
|
||||||
left = int((video_width - width) / 2)
|
|
||||||
box = (left, 0, left + width, video_height)
|
|
||||||
else:
|
|
||||||
height = int(round(video_width / still_ratio))
|
|
||||||
top = int((video_height - height) / 2)
|
|
||||||
box = (0, top, video_width, top + height)
|
|
||||||
if _debug:
|
if _debug:
|
||||||
print frame, 'cut', c, 'still', s, still, 'width', widths[s], box
|
print widths, duration, stills, cuts[c], cuts[c + 1]
|
||||||
#FIXME: why does this have to be still+1?
|
for s in range(int(stills)):
|
||||||
frame_image = Image.open(movie.frame((still+1)/fps))
|
still_ratio = widths[s] / timeline_height
|
||||||
frame_image = frame_image.crop(box).resize((widths[s], timeline_height), Image.ANTIALIAS)
|
if video_ratio > still_ratio:
|
||||||
for x_ in range(widths[s]):
|
width = int(round(video_height * still_ratio))
|
||||||
line_image.append(frame_image.crop((x_, 0, x_ + 1, timeline_height)))
|
left = int((video_width - width) / 2)
|
||||||
still += widths[s]
|
box = (left, 0, left + width, video_height)
|
||||||
timeline_image.paste(line_image[frame], (x, 0))
|
else:
|
||||||
|
height = int(round(video_width / still_ratio))
|
||||||
|
top = int((video_height - height) / 2)
|
||||||
|
box = (0, top, video_width, top + height)
|
||||||
|
if _debug:
|
||||||
|
print frame, 'cut', c, 'still', s, still, 'width', widths[s], box
|
||||||
|
#FIXME: why does this have to be still+1?
|
||||||
|
frame_image = Image.open(movie.frame((still+1)/fps))
|
||||||
|
frame_image = frame_image.crop(box).resize((widths[s], timeline_height), Image.ANTIALIAS)
|
||||||
|
for x_ in range(widths[s]):
|
||||||
|
line_image.append(frame_image.crop((x_, 0, x_ + 1, timeline_height)))
|
||||||
|
still += widths[s]
|
||||||
|
if len(line_image) > frame:
|
||||||
|
timeline_image.paste(line_image[frame], (x, 0))
|
||||||
if x == timeline_width - 1:
|
if x == timeline_width - 1:
|
||||||
timeline_file = '%sstrip.64.%04d.png' % (prefix, i)
|
timeline_file = '%sstrip.64.%04d.png' % (prefix, i)
|
||||||
if _debug:
|
if _debug:
|
||||||
|
|
148
pandora/archive/migrations/0008_available.py
Normal file
148
pandora/archive/migrations/0008_available.py
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
import datetime
|
||||||
|
from south.db import db
|
||||||
|
from south.v2 import SchemaMigration
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
class Migration(SchemaMigration):
|
||||||
|
|
||||||
|
def forwards(self, orm):
|
||||||
|
|
||||||
|
# Deleting field 'File.video_available'
|
||||||
|
db.delete_column('archive_file', 'video_available')
|
||||||
|
|
||||||
|
|
||||||
|
def backwards(self, orm):
|
||||||
|
|
||||||
|
# Adding field 'File.video_available'
|
||||||
|
db.add_column('archive_file', 'video_available', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False)
|
||||||
|
|
||||||
|
|
||||||
|
models = {
|
||||||
|
'archive.file': {
|
||||||
|
'Meta': {'object_name': 'File'},
|
||||||
|
'audio_codec': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||||
|
'available': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||||
|
'bits_per_pixel': ('django.db.models.fields.FloatField', [], {'default': '-1'}),
|
||||||
|
'channels': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'data': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
|
||||||
|
'display_aspect_ratio': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||||
|
'duration': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||||
|
'episode': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
|
||||||
|
'framerate': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||||
|
'height': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'info': ('oxdjango.fields.DictField', [], {'default': '{}'}),
|
||||||
|
'is_audio': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||||
|
'is_extra': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||||
|
'is_main': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||||
|
'is_subtitle': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||||
|
'is_version': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||||
|
'is_video': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||||
|
'language': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '8'}),
|
||||||
|
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||||
|
'movie': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'files'", 'to': "orm['backend.Movie']"}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '2048'}),
|
||||||
|
'oshash': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '16'}),
|
||||||
|
'part': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
|
||||||
|
'pixel_format': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||||
|
'pixels': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
|
||||||
|
'samplerate': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||||
|
'season': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
|
||||||
|
'size': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
|
||||||
|
'sort_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '2048'}),
|
||||||
|
'verified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||||
|
'version': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
|
||||||
|
'video': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
|
||||||
|
'video_codec': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||||
|
'width': ('django.db.models.fields.IntegerField', [], {'default': '0'})
|
||||||
|
},
|
||||||
|
'archive.fileinstance': {
|
||||||
|
'Meta': {'unique_together': "(('name', 'folder', 'volume'),)", 'object_name': 'FileInstance'},
|
||||||
|
'atime': ('django.db.models.fields.IntegerField', [], {'default': '1283966008'}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'ctime': ('django.db.models.fields.IntegerField', [], {'default': '1283966008'}),
|
||||||
|
'file': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'instances'", 'to': "orm['archive.File']"}),
|
||||||
|
'folder': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||||
|
'mtime': ('django.db.models.fields.IntegerField', [], {'default': '1283966008'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '2048'}),
|
||||||
|
'volume': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'files'", 'to': "orm['archive.Volume']"})
|
||||||
|
},
|
||||||
|
'archive.frame': {
|
||||||
|
'Meta': {'unique_together': "(('file', 'position'),)", 'object_name': 'Frame'},
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'file': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'frames'", 'to': "orm['archive.File']"}),
|
||||||
|
'frame': ('django.db.models.fields.files.ImageField', [], {'default': 'None', 'max_length': '100', 'null': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||||
|
'position': ('django.db.models.fields.FloatField', [], {})
|
||||||
|
},
|
||||||
|
'archive.volume': {
|
||||||
|
'Meta': {'unique_together': "(('user', 'name'),)", 'object_name': 'Volume'},
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
|
||||||
|
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'volumes'", 'to': "orm['auth.User']"})
|
||||||
|
},
|
||||||
|
'auth.group': {
|
||||||
|
'Meta': {'object_name': 'Group'},
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||||
|
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||||
|
},
|
||||||
|
'auth.permission': {
|
||||||
|
'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||||
|
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||||
|
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||||
|
},
|
||||||
|
'auth.user': {
|
||||||
|
'Meta': {'object_name': 'User'},
|
||||||
|
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||||
|
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||||
|
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||||
|
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
|
||||||
|
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||||
|
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||||
|
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||||
|
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||||
|
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||||
|
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||||
|
},
|
||||||
|
'backend.movie': {
|
||||||
|
'Meta': {'object_name': 'Movie'},
|
||||||
|
'available': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True', 'blank': 'True'}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'imdb': ('oxdjango.fields.DictField', [], {'default': '{}'}),
|
||||||
|
'json': ('oxdjango.fields.DictField', [], {'default': '{}'}),
|
||||||
|
'metadata': ('oxdjango.fields.DictField', [], {'default': '{}'}),
|
||||||
|
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||||
|
'movieId': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128', 'blank': 'True'}),
|
||||||
|
'oxdbId': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '42', 'blank': 'True'}),
|
||||||
|
'poster': ('django.db.models.fields.files.ImageField', [], {'default': 'None', 'max_length': '100', 'blank': 'True'}),
|
||||||
|
'poster_frame': ('django.db.models.fields.FloatField', [], {'default': '-1'}),
|
||||||
|
'poster_height': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||||
|
'poster_url': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||||
|
'poster_width': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||||
|
'published': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||||
|
'stream_aspect': ('django.db.models.fields.FloatField', [], {'default': '1.3333333333333333'})
|
||||||
|
},
|
||||||
|
'contenttypes.contenttype': {
|
||||||
|
'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||||
|
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
complete_apps = ['archive']
|
|
@ -140,7 +140,6 @@ class File(models.Model):
|
||||||
return r
|
return r
|
||||||
|
|
||||||
#upload and data handling
|
#upload and data handling
|
||||||
video_available = models.BooleanField(default=False)
|
|
||||||
video = models.FileField(null=True, blank=True, upload_to=lambda f, x: file_path(f, '%s.webm'%settings.VIDEO_PROFILE))
|
video = models.FileField(null=True, blank=True, upload_to=lambda f, x: file_path(f, '%s.webm'%settings.VIDEO_PROFILE))
|
||||||
data = models.FileField(null=True, blank=True, upload_to=lambda f, x: file_path(f, 'data.raw'))
|
data = models.FileField(null=True, blank=True, upload_to=lambda f, x: file_path(f, 'data.raw'))
|
||||||
|
|
||||||
|
@ -154,7 +153,7 @@ class File(models.Model):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def save_chunk(self, chunk, chunk_id=-1):
|
def save_chunk(self, chunk, chunk_id=-1):
|
||||||
if not self.video_available:
|
if not self.available:
|
||||||
if not self.video:
|
if not self.video:
|
||||||
self.video.save('%s.webm'%settings.VIDEO_PROFILE, chunk)
|
self.video.save('%s.webm'%settings.VIDEO_PROFILE, chunk)
|
||||||
else:
|
else:
|
||||||
|
@ -202,11 +201,10 @@ class FileInstance(models.Model):
|
||||||
def movieId(self):
|
def movieId(self):
|
||||||
return File.objects.get(oshash=self.oshash).movieId
|
return File.objects.get(oshash=self.oshash).movieId
|
||||||
|
|
||||||
def frame_path(f, name):
|
def frame_path(frame, name):
|
||||||
ext = os.path.splitext(name)[-1]
|
ext = os.path.splitext(name)[-1]
|
||||||
name = "%s%s" % (f.position, ext)
|
name = "%s%s" % (frame.position, ext)
|
||||||
h = f.file.oshash
|
return file_path(frame.file, name)
|
||||||
return os.path.join('frame', h[:2], h[2:4], h[4:6], name)
|
|
||||||
|
|
||||||
class Frame(models.Model):
|
class Frame(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
@ -170,6 +170,7 @@ def api_upload(request):
|
||||||
'''
|
'''
|
||||||
user = request.user
|
user = request.user
|
||||||
f = get_object_or_404(models.File, oshash=request.POST['oshash'])
|
f = get_object_or_404(models.File, oshash=request.POST['oshash'])
|
||||||
|
print request.FILES
|
||||||
if 'frame' in request.FILES:
|
if 'frame' in request.FILES:
|
||||||
if f.frames.count() == 0:
|
if f.frames.count() == 0:
|
||||||
for frame in request.FILES.getlist('frame'):
|
for frame in request.FILES.getlist('frame'):
|
||||||
|
@ -230,7 +231,7 @@ def firefogg_upload(request):
|
||||||
if f.editable(request.user):
|
if f.editable(request.user):
|
||||||
if f.video:
|
if f.video:
|
||||||
f.video.delete()
|
f.video.delete()
|
||||||
f.video_available = False
|
f.available = False
|
||||||
f.save()
|
f.save()
|
||||||
response = {
|
response = {
|
||||||
#is it possible to no hardcode url here?
|
#is it possible to no hardcode url here?
|
||||||
|
|
|
@ -71,16 +71,6 @@ def getMovie(info):
|
||||||
movie.save()
|
movie.save()
|
||||||
return movie
|
return movie
|
||||||
|
|
||||||
def movie_path(f, size):
|
|
||||||
name = "%s.%s" % (size, 'ogv')
|
|
||||||
url_hash = f.movieId
|
|
||||||
return os.path.join('movie', url_hash[:2], url_hash[2:4], url_hash[4:6], name)
|
|
||||||
|
|
||||||
def poster_path(f):
|
|
||||||
name = "%s.%s" % (f.movieId, 'jpg')
|
|
||||||
url_hash = f.movieId
|
|
||||||
return os.path.join('poster', url_hash[:2], url_hash[2:4], url_hash[4:6], name)
|
|
||||||
|
|
||||||
class Movie(models.Model):
|
class Movie(models.Model):
|
||||||
person_keys = ('director', 'writer', 'producer', 'editor', 'cinematographer', 'actor', 'character')
|
person_keys = ('director', 'writer', 'producer', 'editor', 'cinematographer', 'actor', 'character')
|
||||||
facet_keys = person_keys + ('country', 'language', 'genre', 'keyword')
|
facet_keys = person_keys + ('country', 'language', 'genre', 'keyword')
|
||||||
|
@ -137,7 +127,7 @@ class Movie(models.Model):
|
||||||
self.imdb = ox.web.imdb.Imdb(self.movieId)
|
self.imdb = ox.web.imdb.Imdb(self.movieId)
|
||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
poster = models.ImageField(default=None, blank=True, upload_to=lambda f, x: poster_path(f))
|
poster = models.ImageField(default=None, blank=True, upload_to=lambda m, x: os.path.join(movieid_path(m.movieId), "poster.jpg"))
|
||||||
poster_url = models.TextField(blank=True)
|
poster_url = models.TextField(blank=True)
|
||||||
poster_height = models.IntegerField(default=0)
|
poster_height = models.IntegerField(default=0)
|
||||||
poster_width = models.IntegerField(default=0)
|
poster_width = models.IntegerField(default=0)
|
||||||
|
@ -395,7 +385,7 @@ class Movie(models.Model):
|
||||||
n = self.files.count() * 3
|
n = self.files.count() * 3
|
||||||
frame = int(math.floor(n/2))
|
frame = int(math.floor(n/2))
|
||||||
part = 1
|
part = 1
|
||||||
for f in self.files.filter(is_main=True, video_available=True):
|
for f in self.files.filter(is_main=True, available=True):
|
||||||
for frame in f.frames.all():
|
for frame in f.frames.all():
|
||||||
path = os.path.abspath(os.path.join(settings.MEDIA_ROOT, poster_path(self)))
|
path = os.path.abspath(os.path.join(settings.MEDIA_ROOT, poster_path(self)))
|
||||||
path = path.replace('.jpg', '%s.%s.jpg'%(part, frame.pos))
|
path = path.replace('.jpg', '%s.%s.jpg'%(part, frame.pos))
|
||||||
|
@ -415,11 +405,11 @@ class Movie(models.Model):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def timeline_prefix(self):
|
def timeline_prefix(self):
|
||||||
return os.path.join(settings.MEDIA_ROOT, 'stream', movieid_path(self.movieId), 'timeline')
|
return os.path.join(settings.MEDIA_ROOT, movieid_path(self.movieId), 'timeline')
|
||||||
|
|
||||||
def updateStreams(self):
|
def updateStreams(self):
|
||||||
files = {}
|
files = {}
|
||||||
for f in self.files.filter(is_main=True, video_available=True):
|
for f in self.files.filter(is_main=True, available=True):
|
||||||
files[utils.sort_title(f.name)] = f.video.path
|
files[utils.sort_title(f.name)] = f.video.path
|
||||||
|
|
||||||
#FIXME: how to detect if something changed?
|
#FIXME: how to detect if something changed?
|
||||||
|
@ -429,24 +419,23 @@ class Movie(models.Model):
|
||||||
cmd = []
|
cmd = []
|
||||||
|
|
||||||
for f in sorted(files):
|
for f in sorted(files):
|
||||||
if not cmd:
|
cmd.append('+')
|
||||||
cmd.append(files[f])
|
cmd.append(files[f])
|
||||||
else:
|
|
||||||
cmd.append('+')
|
|
||||||
cmd.append(files[f])
|
|
||||||
if not os.path.exists(os.path.dirname(stream.video.path)):
|
if not os.path.exists(os.path.dirname(stream.video.path)):
|
||||||
os.makedirs(os.path.dirname(stream.video.path))
|
os.makedirs(os.path.dirname(stream.video.path))
|
||||||
cmd = [ 'mkvmerge', '-o', stream.video.path ] + cmd
|
cmd = [ 'mkvmerge', '-o', stream.video.path ] + cmd[1:]
|
||||||
subprocess.Popen(cmd)
|
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
p.wait()
|
||||||
stream.save()
|
stream.save()
|
||||||
|
|
||||||
extract.timeline(stream.video.path, self.timeline_prefix)
|
if 'video' in stream.info:
|
||||||
|
extract.timeline(stream.video.path, self.timeline_prefix)
|
||||||
extract.timeline_strip(self, self.metadata['cuts'], stream.info, self.timeline_prefix[:-8])
|
self.stream_aspect = stream.info['video'][0]['width']/stream.info['video'][0]['height']
|
||||||
|
self.metadata['cuts'] = extract.cuts(self.timeline_prefix)
|
||||||
|
self.metadata['average_color'] = extract.average_color(self.timeline_prefix)
|
||||||
|
extract.timeline_strip(self, self.metadata['cuts'], stream.info, self.timeline_prefix[:-8])
|
||||||
|
|
||||||
stream.extract_derivatives()
|
stream.extract_derivatives()
|
||||||
self.metadata['cuts'] = extract.cuts(self.timeline_prefix)
|
|
||||||
self.metadata['average_color'] = extract.average_color(self.timeline_prefix)
|
|
||||||
#something with poster
|
#something with poster
|
||||||
self.available = True
|
self.available = True
|
||||||
self.save()
|
self.save()
|
||||||
|
@ -719,10 +708,10 @@ class Collection(models.Model):
|
||||||
|
|
||||||
|
|
||||||
def movieid_path(h):
|
def movieid_path(h):
|
||||||
return os.path.join(h[:2], h[2:4], h[4:6], h[6:])
|
return os.path.join('movie', h[:2], h[2:4], h[4:6], h[6:])
|
||||||
def stream_path(f):
|
|
||||||
h = f.movie.movieId
|
def stream_path(stream):
|
||||||
return os.path.join('stream', movieid_path(h), f.profile)
|
return os.path.join(movieid_path(stream.movie.movieId), stream.profile)
|
||||||
|
|
||||||
class Stream(models.Model):
|
class Stream(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
@ -59,7 +59,7 @@ var app = new Ox.App({
|
||||||
Ox.print('requestStop')
|
Ox.print('requestStop')
|
||||||
app.$ui.loadingIcon.stop();
|
app.$ui.loadingIcon.stop();
|
||||||
});
|
});
|
||||||
|
$.each(app.afterLaunch, function(i, f) { f() });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
$(function() {
|
if(typeof(app.afterLaunch) == "undefined")
|
||||||
|
app.afterLaunch = [];
|
||||||
|
app.afterLaunch.push(function() {
|
||||||
if (typeof(OxFF) == 'undefined')
|
if (typeof(OxFF) == 'undefined')
|
||||||
return;
|
return;
|
||||||
app.local = {
|
app.local = {
|
||||||
|
@ -53,6 +55,7 @@ $(function() {
|
||||||
if(!cb)
|
if(!cb)
|
||||||
return null;
|
return null;
|
||||||
return function(result) {
|
return function(result) {
|
||||||
|
Ox.print("you called upload", result);
|
||||||
var data = JSON.parse(result);
|
var data = JSON.parse(result);
|
||||||
cb(data)
|
cb(data)
|
||||||
}
|
}
|
||||||
|
@ -211,41 +214,58 @@ $(function() {
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
app.local.files(name, function(result) {
|
app.local.files(name, function(result) {
|
||||||
|
var fileInfo = result.info;
|
||||||
app.request('update', {
|
app.request('update', {
|
||||||
'volume': name, 'files': result.files
|
'volume': name, 'files': result.files
|
||||||
}, function(result) {
|
}, function(result) {
|
||||||
var videos = {};
|
var videos = {};
|
||||||
$.each(result.data.data, function(i, oshash) {
|
function parseResult(result) {
|
||||||
$.each(folder_ids, function(i, ids) {
|
$.each(result.data.data, function(i, oshash) {
|
||||||
if($.inArray(oshash, ids) > -1) {
|
$.each(folder_ids, function(i, ids) {
|
||||||
if(!videos[i]) {
|
if($.inArray(oshash, ids) > -1) {
|
||||||
videos[i] = [];
|
if(!videos[i]) {
|
||||||
var button = new Ox.Button({
|
videos[i] = [];
|
||||||
id: 'upload_' + oshash,
|
var button = new Ox.Button({
|
||||||
title: 'Upload',
|
id: 'upload_' + oshash,
|
||||||
width: 48
|
title: 'Upload',
|
||||||
}).bindEvent('click', function(fid) { return function(event, data) {
|
width: 48
|
||||||
Ox.print(videos[fid]);
|
}).bindEvent('click', function(fid) { return function(event, data) {
|
||||||
//$($('#'+fid).find('.OxCell')[2]).html('extracting data...');
|
Ox.print(videos[fid]);
|
||||||
app.local.uploadVideos(
|
//$($('#'+fid).find('.OxCell')[2]).html('extracting data...');
|
||||||
videos[fid],
|
app.local.uploadVideos(
|
||||||
function(data) {
|
videos[fid],
|
||||||
$($('#'+fid).find('.OxCell')[2]).html('done');
|
function(data) {
|
||||||
},
|
$($('#'+fid).find('.OxCell')[2]).html('done');
|
||||||
function(data) {
|
},
|
||||||
$($('#'+fid).find('.OxCell')[2]).html(data.status +': '+ data.progress);
|
function(data) {
|
||||||
}
|
$($('#'+fid).find('.OxCell')[2]).html(data.status +': '+ data.progress);
|
||||||
);
|
}
|
||||||
}}(i));
|
);
|
||||||
$($('#'+i).find('.OxCell')[2]).html(button.$element);
|
}}(i));
|
||||||
$('#'+i).css({'font-weight': 'bold'});
|
$($('#'+i).find('.OxCell')[2]).html(button.$element);
|
||||||
|
$('#'+i).css({'font-weight': 'bold'});
|
||||||
|
}
|
||||||
|
videos[i].push(oshash);
|
||||||
|
//add some double click callback here to trigger video upload
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
videos[i].push(oshash);
|
});
|
||||||
//add some double click callback here to trigger video upload
|
});
|
||||||
return false;
|
};
|
||||||
|
if (result.data.info.length>0) {
|
||||||
|
var post = {'info': {}};
|
||||||
|
$.each(result.data.info, function(i, oshash) {
|
||||||
|
if(fileInfo[oshash]) {
|
||||||
|
post.info[oshash] = fileInfo[oshash];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
app.request('update', post, function(result) {
|
||||||
|
parseResult(result);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
parseResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
var data = {
|
var data = {
|
||||||
items: []
|
items: []
|
||||||
|
@ -303,10 +323,5 @@ $(function() {
|
||||||
return url;
|
return url;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
app.local.loadVolumes();
|
||||||
if(typeof(app.afterLaunch) == "undefined")
|
|
||||||
app.afterLaunch = [];
|
|
||||||
app.afterLaunch.push(function() {
|
|
||||||
app.local.loadVolumes();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -23,7 +23,7 @@ $(function() {
|
||||||
posterFrame = 1515,
|
posterFrame = 1515,
|
||||||
points = [2059, 2748],
|
points = [2059, 2748],
|
||||||
videoId = document.location.hash.substring(1),
|
videoId = document.location.hash.substring(1),
|
||||||
videoUrl = "/" + videoId + "/96p." + ($.support.video.webm ? "webm": "mp4").
|
videoUrl = "/" + videoId + "/96p." + ($.support.video.webm ? "webm": "mp4"),
|
||||||
stripTimeline = false;
|
stripTimeline = false;
|
||||||
|
|
||||||
$.getJSON("/" + videoId + "/data/video.json", function(video) {
|
$.getJSON("/" + videoId + "/data/video.json", function(video) {
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
<script type="text/javascript" src="/static/oxjs/build/js/ox.ui.js"></script>
|
<script type="text/javascript" src="/static/oxjs/build/js/ox.ui.js"></script>
|
||||||
<script type="text/javascript" src="/site.js"></script>
|
<script type="text/javascript" src="/site.js"></script>
|
||||||
<script type="text/javascript" src="/static/js/pandora.js"></script>
|
<script type="text/javascript" src="/static/js/pandora.js"></script>
|
||||||
|
<script type="text/javascript" src="/static/js/pandora.local.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body></body>
|
<body></body>
|
||||||
</html>
|
</html>
|
||||||
|
|
Loading…
Reference in a new issue