uploads, transcodes, /ra

This commit is contained in:
j 2010-08-24 19:16:33 +02:00
parent b81d08fae5
commit fba5070bc2
9 changed files with 128 additions and 40 deletions

View file

@ -8,6 +8,10 @@ from oxdjango.shortcuts import json_response, render_to_json_response, get_objec
import models import models
def intro(request):
context = RequestContext(request, {'settings':settings})
return render_to_response('intro.html', context)
def index(request): def index(request):
context = RequestContext(request, {'settings':settings}) context = RequestContext(request, {'settings':settings})
return render_to_response('index.html', context) return render_to_response('index.html', context)

View file

@ -24,6 +24,9 @@ from backend import utils
from backend import extract from backend import extract
from pandora.backend.models import Movie from pandora.backend.models import Movie
import extract
def parse_decimal(string): def parse_decimal(string):
string = string.replace(':', '/') string = string.replace(':', '/')
if '/' not in string: if '/' not in string:
@ -133,6 +136,11 @@ class File(models.Model):
r[k] = unicode(self[k]) r[k] = unicode(self[k])
return r return r
def contents(self):
if self.contents_set.count() > 0:
return self.contents_set.all()[0].data
return None
class Volume(models.Model): class Volume(models.Model):
class Meta: class Meta:
unique_together = ("user", "name") unique_together = ("user", "name")
@ -171,8 +179,8 @@ class FileInstance(models.Model):
return File.objects.get(oshash=self.oshash).movieId return File.objects.get(oshash=self.oshash).movieId
def frame_path(f, name): def frame_path(f, name):
ext = os.path.splitext(name) ext = os.path.splitext(name)[-1]
name = "%s.%s" % (f.position, ext) name = "%s%s" % (f.position, ext)
h = f.file.oshash h = f.file.oshash
return os.path.join('frame', h[:2], h[2:4], h[4:6], name) return os.path.join('frame', h[:2], h[2:4], h[4:6], name)
@ -188,7 +196,7 @@ class Frame(models.Model):
#FIXME: frame path should be renamed on save to match current position #FIXME: frame path should be renamed on save to match current position
def __unicode__(self): def __unicode__(self):
return '%s at %s' % (self.file, self.position) return u'%s at %s' % (self.file, self.position)
def stream_path(f): def stream_path(f):
h = f.file.oshash h = f.file.oshash
@ -204,10 +212,43 @@ class Stream(models.Model):
source = models.ForeignKey('Stream', related_name='derivatives', default=None, null=True) source = models.ForeignKey('Stream', related_name='derivatives', default=None, null=True)
available = models.BooleanField(default=False) available = models.BooleanField(default=False)
def __unicode__(self):
return self.video
def extract_derivates(self): def extract_derivates(self):
#here based on settings derivates like smaller versions or other formats would be created if settings.VIDEO_H264:
profile = self.profile.replace('.webm', '.mp4')
if Stream.objects.filter(profile=profile, source=self).count() == 0:
derivate = Stream(file=self.file, source=self, profile=profile)
derivate.video.name = self.video.name.replace(self.profile, profile)
derivate.encode()
for p in settings.VIDEO_DERIVATIVES:
profile = p + '.webm'
target = self.video.path.replace(self.profile, profile)
if Stream.objects.filter(profile=profile, source=self).count() == 0:
derivate = Stream(file=self.file, source=self, profile=profile)
derivate.video.name = self.video.name.replace(self.profile, profile)
derivate.encode()
if settings.VIDEO_H264:
profile = p + '.mp4'
if Stream.objects.filter(profile=profile, source=self).count() == 0:
derivate = Stream(file=self.file, source=self, profile=profile)
derivate.video.name = self.video.name.replace(self.profile, profile)
derivate.encode()
return True return True
def encode(self):
if self.source:
video = self.source.video.path
target = self.video.path
profile = self.profile
info = self.file.info
if extract.stream(video, target, profile, info):
self.available=True
self.save()
def editable(self, user): def editable(self, user):
#FIXME: possibly needs user setting for stream #FIXME: possibly needs user setting for stream
return True return True
@ -230,4 +271,15 @@ class Stream(models.Model):
self.file.save() self.file.save()
super(Stream, self).save(*args, **kwargs) super(Stream, self).save(*args, **kwargs)
class FileContents(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
file = models.ForeignKey(File, related_name="contents_set")
data = models.TextField(default=u'')
def save(self, *args, **kwargs):
if self.data and not self.file.available:
self.file.available = True
self.file.save()
super(FileContents, self).save(*args, **kwargs)

View file

@ -159,25 +159,34 @@ def api_update(request):
@login_required_json @login_required_json
#FIXME: is this part of the api or does it have to be outside due to multipart?
def api_upload(request): def api_upload(request):
''' '''
multipart
param data
oshash: string oshash: string
frame: [] //multipart frames frame: [] //multipart frames
file: [] //multipart file
return {'status': {'code': int, 'text': string}, return {'status': {'code': int, 'text': string},
'data': {info: object, rename: object}} 'data': {info: object, rename: object}}
''' '''
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'])
if f.frames.count() == 0 and 'frame' in request.FILES: if 'frame' in request.FILES:
for frame in request.FILES['frame']: if f.frames.count() == 0:
for frame in request.FILES.getlist('frame'):
name = frame.name name = frame.name
#float required?
position = float(os.path.splitext(name)[0]) position = float(os.path.splitext(name)[0])
fr = models.Frame(file=f, position=position) fr = models.Frame(file=f, position=position)
fr.save() fr.save()
fr.frame.save(frame, name) fr.frame.save(name, frame)
response = json_response({})
else:
response = json_response(status=403, text='permissino denied')
if 'file' in request.FILES:
if f.contents.count() == 0:
contents = models.FileContents(file=f)
contents.data = request.FILES['file'].read()
contents.save()
response = json_response({}) response = json_response({})
else: else:
response = json_response(status=403, text='permissino denied') response = json_response(status=403, text='permissino denied')
@ -198,7 +207,6 @@ def firefogg_upload(request):
#post next chunk #post next chunk
if 'chunk' in request.FILES and oshash: if 'chunk' in request.FILES and oshash:
print "all chunk now"
stream = get_object_or_404(models.Stream, file__oshash=oshash, profile=profile) stream = get_object_or_404(models.Stream, file__oshash=oshash, profile=profile)
form = VideoChunkForm(request.POST, request.FILES) form = VideoChunkForm(request.POST, request.FILES)
@ -233,7 +241,6 @@ def firefogg_upload(request):
'result': 1 'result': 1
} }
return render_to_json_response(response) return render_to_json_response(response)
print request.GET, request.POST
response = json_response(status=400, text='this request requires POST') response = json_response(status=400, text='this request requires POST')
return render_to_json_response(response) return render_to_json_response(response)

View file

@ -73,3 +73,5 @@ def resize_image(image_source, image_output, width):
resize_method = Image.BICUBIC resize_method = Image.BICUBIC
output = source.resize((width, height), resize_method) output = source.resize((width, height), resize_method)
output.save(image_output) output.save(image_output)

View file

@ -25,11 +25,6 @@ import load
import utils import utils
import extract import extract
def plural_key(term):
return {
'country': 'countries',
}.get(term, term + 's')
def getMovie(info): def getMovie(info):
''' '''
@ -210,6 +205,7 @@ class Movie(models.Model):
else: else:
movie[pub_key] = value movie[pub_key] = value
movie['poster'] = self.get_poster() movie['poster'] = self.get_poster()
if fields: if fields:
for f in fields: for f in fields:
if f.endswith('.length') and f[:-7] in ('cast', 'genre', 'trivia'): if f.endswith('.length') and f[:-7] in ('cast', 'genre', 'trivia'):
@ -231,6 +227,13 @@ class Movie(models.Model):
self.get('series title', ''), self.get('episode title', ''), self.get('series title', ''), self.get('episode title', ''),
self.get('season', ''), self.get('episode', '')) self.get('season', ''), self.get('episode', ''))
def streams(self):
streams = []
for f in self.files.filter(is_main=True, available=True):
for s in f.streams.all():
streams.append(s.video.url)
return streams
def frame(self, position, width=128): def frame(self, position, width=128):
#FIXME: compute offset and so on #FIXME: compute offset and so on
f = self.files.all()[0] f = self.files.all()[0]
@ -254,7 +257,7 @@ class Movie(models.Model):
elif key == 'character': elif key == 'character':
values = [i[1] for i in self.get('actor', [])] values = [i[1] for i in self.get('actor', [])]
else: else:
values = self.get(plural_key(key), []) values = self.get(utils.plural_key(key), [])
setattr(f, key, '|%s|'%'|'.join(values)) setattr(f, key, '|%s|'%'|'.join(values))
f.summary = self.get('plot', '') + self.get('plot_outline', '') f.summary = self.get('plot', '') + self.get('plot_outline', '')
@ -303,10 +306,10 @@ class Movie(models.Model):
s.year = self.get('year', '') s.year = self.get('year', '')
for key in self.person_keys: for key in self.person_keys:
setattr(s, key, sortNames(self.get(plural_key(key), []))) setattr(s, key, sortNames(self.get(utils.plural_key(key), [])))
for key in ('language', 'country'): for key in ('language', 'country'):
setattr(s, key, ','.join(self.get(plural_key(key), []))) setattr(s, key, ','.join(self.get(utils.plural_key(key), [])))
s.runtime = self.get('runtime', 0) s.runtime = self.get('runtime', 0)
@ -351,7 +354,7 @@ class Movie(models.Model):
elif key == 'character': elif key == 'character':
current_values = [i[1] for i in self.get('actor', [])] current_values = [i[1] for i in self.get('actor', [])]
else: else:
current_values = self.get(plural_key(key), []) current_values = self.get(utils.plural_key(key), [])
saved_values = [i.value for i in Facet.objects.filter(movie=self, key=key)] saved_values = [i.value for i in Facet.objects.filter(movie=self, key=key)]
removed_values = filter(lambda x: x not in current_values, saved_values) removed_values = filter(lambda x: x not in current_values, saved_values)
if removed_values: if removed_values:
@ -625,7 +628,6 @@ class Layer(models.Model):
return True return True
return False return False
class Collection(models.Model): class Collection(models.Model):
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)

View file

@ -12,6 +12,12 @@ import ox
import ox.iso import ox.iso
from ox.normalize import normalizeName, normalizeTitle from ox.normalize import normalizeName, normalizeTitle
def plural_key(term):
return {
'country': 'countries',
}.get(term, term + 's')
def oxid(title, directors, year='', seriesTitle='', episodeTitle='', season=0, episode=0): def oxid(title, directors, year='', seriesTitle='', episodeTitle='', season=0, episode=0):
director = ', '.join(directors) director = ', '.join(directors)
oxid_value = u"\n".join([title, director, year]) oxid_value = u"\n".join([title, director, year])

View file

@ -120,14 +120,18 @@ INSTALLED_APPS = (
AUTH_PROFILE_MODULE = 'oxuser.UserProfile' AUTH_PROFILE_MODULE = 'oxuser.UserProfile'
#Video encoding settings #Video encoding settings
VIDEO_PROFILE = 'low' # possible values low, mid or high #available profiles: 96p, 270p, 360p, 480p, 720p, 1080p
VIDEO_ENCODING = {
'low': {'height': 96, 'videoBitrate': 180, 'softTarget': True, VIDEO_PROFILE = '96p'
'samplerate': 44100, 'audioQuality': -1, 'channels': 1, 'noUpscaling': True}, VIDEO_DERIVATIVES = []
'mid': {'maxSize': 320, 'videoBitrate': 500, VIDEO_H264 = True
'samplerate': 44100, 'audioQuality': 0, 'channels': 1, 'noUpscaling': True},
'high': {'profile': 'padma'}
} #Pad.ma
#VIDEO_PROFILE = '480p'
#VIDEO_DERIVATIVES = ['96p', '270p', '360p']
#VIDEO_H264 = False
TRANSMISSON_HOST='localhost' TRANSMISSON_HOST='localhost'
TRANSMISSON_PORT=9091 TRANSMISSON_PORT=9091

View file

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<title>pan.do/ra</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
this is a pan.do/ra development preview, <a href="/ra">click here to continue</a>
</body>
</html>

View file

@ -13,7 +13,8 @@ urlpatterns = patterns('',
(r'^api/', include('backend.urls')), (r'^api/', include('backend.urls')),
(r'^api/upload/$', 'archive.views.firefogg_upload'), (r'^api/upload/$', 'archive.views.firefogg_upload'),
(r'^site.js$', 'app.views.site_js'), (r'^site.js$', 'app.views.site_js'),
(r'^$', 'app.views.index'), (r'^$', 'app.views.intro'),
(r'^ra$', 'app.views.index'),
(r'^r/(?P<key>.*)$', 'oxuser.views.recover'), (r'^r/(?P<key>.*)$', 'oxuser.views.recover'),
# Uncomment the admin/doc line below and add 'django.contrib.admindocs' # Uncomment the admin/doc line below and add 'django.contrib.admindocs'