serve frames, timelines and videos, wire up timeline demo

This commit is contained in:
j 2010-09-08 13:56:58 +02:00
commit f3f40f6e2f
10 changed files with 1595 additions and 68 deletions

View file

@ -259,9 +259,11 @@ class Movie(models.Model):
self.get('season', ''), self.get('episode', ''))
def frame(self, position, width=128):
#FIXME: compute offset and so on
f = self.files.all()[0]
return f.frame(position, width)
stream = self.streams.filter(profile=settings.VIDEO_PROFILE+'.webm')[0]
path = os.path.join(settings.MEDIA_ROOT, 'frame', self.movieId, "%d"%width, "%s.jpg"%position)
if not os.path.exists(path):
extract.frame(stream.video.path, path, position, width)
return path
def updateFind(self):
try:
@ -411,6 +413,10 @@ class Movie(models.Model):
subprocess.Popen(cmd)
part += 1
@property
def timeline_prefix(self):
return os.path.join('stream', movieid_path(self.movieId), 'timeline')
def updateStreams(self):
files = {}
for f in self.files.filter(is_main=True, video_available=True):
@ -428,11 +434,13 @@ class Movie(models.Model):
else:
cmd.append('+')
cmd.append(files[f])
if not os.path.exists(os.path.dirname(stream.video.path)):
os.makedirs(os.path.dirname(stream.video.path))
cmd = [ 'mkvmerge', '-o', stream.video.path ] + cmd
subprocess.Popen(cmd)
stream.save()
extract.timeline(stream.video.path, os.path.join(stream.video.path[:-len(stream.profile)], 'timeline'))
extract.timeline(stream.video.path, os.path.join(settings.MEDIA_ROOT, self.timeline_prefix))
stream.extract_derivatives()
#something with poster
@ -704,10 +712,13 @@ class Collection(models.Model):
def editable(self, user):
return self.users.filter(id=user.id).count() > 0
def movieid_path(h):
return os.path.join(h[:2], h[2:4], h[4:6], h[6:])
def stream_path(f):
h = f.movie.movieId
return os.path.join('stream', h[:2], h[2:4], h[4:6], h[6:], f.profile)
return os.path.join('stream', movieid_path(h), f.profile)
class Stream(models.Model):
class Meta:

View file

@ -5,10 +5,13 @@ from django.conf.urls.defaults import *
urlpatterns = patterns("backend.views",
(r'^frame/(?P<id>.*)/(?P<position>.*)\.(?P<size>\d+).jpg$', 'frame'),
(r'^stream/(?P<id>.*).(?P<quality>.*).ogv$', 'video'),
(r'^poster/(?P<id>.*)\.(?P<size>\d+)\.jpg$', 'poster'),
(r'^poster/(?P<id>.*)\.jpg$', 'poster'),
(r'^(?P<id>.*)/frame/(?P<size>\d+)/(?P<position>[0-9\.,]+).jpg$', 'frame'),
(r'^(?P<id>.*)/(?P<profile>.*.webm)$', 'video'),
(r'^(?P<id>.*)/(?P<profile>.*.mp4)$', 'video'),
(r'^(?P<id>.*)/poster\.(?P<size>\d+)\.jpg$', 'poster'),
(r'^(?P<id>.*)/poster\.jpg$', 'poster'),
(r'^(?P<id>.*)/timelines/timeline\.(?P<size>\d+)\.(?P<position>\d+)\.png$', 'timeline'),
(r'^(?P<id>.*)/data/(?P<data>.+)\.json$', 'data'),
(r'^api/$', 'api'),
)

View file

@ -494,45 +494,6 @@ def api_getImdbId(request):
response = json_response(status=404, text='not found')
return render_to_json_response(response)
def poster(request, id, size=None):
print id, size
movie = get_object_or_404(models.Movie, movieId=id)
if movie.poster:
if size:
size = int(size)
poster_path = movie.poster.path.replace('.jpg', '.%d.jpg'%size)
if not os.path.exists(poster_path):
poster_size = max(movie.poster.width, movie.poster.height)
size = min(size, poster_size)
poster_path = movie.poster.path.replace('.jpg', '.%d.jpg'%size)
extract.resize_image(movie.poster.path, poster_path, size=size)
url = movie.poster.url.replace('.jpg', '.%d.jpg'%size)
elif movie.poster:
url = movie.poster.url
else:
url = movie.poster_url
if not url:
url = '/static/png/posterDark.48.png'
return redirect(url)
def video(request, id, quality):
movie = get_object_or_404(models.Movie, movieId=id)
if quality not in settings.VIDEO_ENCODING:
raise Http404
stream = getattr(movie, 'stream_'+quality)
response = HttpFileResponse(stream.path, content_type='video/ogg')
#FIXME: movie needs duration field
#response['Content-Duration'] = movie.duration
return response
def frame(request, id, position, size):
movie = get_object_or_404(models.Movie, movieId=id)
position = ox.time2ms(position)/1000
frame = movie.frame(position, int(size))
if not frame:
raise Http404
return HttpFileResponse(frame, content_type='image/jpeg')
def apidoc(request):
'''
this is used for online documentation at http://127.0.0.1:8000/api/
@ -573,3 +534,53 @@ def apidoc(request):
context = RequestContext(request, {'api': api,
'sitename': settings.SITENAME,})
return render_to_response('api.html', context)
def data(request, id, data):
movie = get_object_or_404(models.Movie, movieId=id)
response = {}
if data == 'video':
response = movie.get_stream()
return render_to_json_response(response)
#media delivery
def frame(request, id, position, size):
movie = get_object_or_404(models.Movie, movieId=id)
position = float(position.replace(',', '.'))
frame = movie.frame(position, int(size))
if not frame:
raise Http404
return HttpFileResponse(frame, content_type='image/jpeg')
def poster(request, id, size=128):
movie = get_object_or_404(models.Movie, movieId=id)
if size == 'large':
size = None
if movie.poster:
if size:
size = int(size)
poster_path = movie.poster.path.replace('.jpg', '.%d.jpg'%size)
if not os.path.exists(poster_path):
poster_size = max(movie.poster.width, movie.poster.height)
if size > poster_size:
return redirect('/%s/poster.large.jpg' % movie.movieId)
extract.resize_image(movie.poster.path, poster_path, size=size)
else:
poster_path = movie.poster.path
else:
poster_path = os.path.join(settings.STATIC_ROOT, 'png/posterDark.48.png')
return HttpFileResponse(poster_path, content_type='image/jpeg')
def timeline(request, id, size, position):
movie = get_object_or_404(models.Movie, movieId=id)
timeline = os.path.join(settings.MEDIA_ROOT, '%s.%s.%04d.png' %(movie.timeline_prefix, size, int(position)))
return HttpFileResponse(timeline, content_type='image/png')
def video(request, id, profile):
movie = get_object_or_404(models.Movie, movieId=id)
stream = get_object_or_404(movie.streams, profile=profile)
path = stream.video.path
content_type = path.endswith('.mp4') and 'video/mp4' or 'video/webm'
#url = 'http://127.0.0.1/pandora_media' + path[len(settings.MEDIA_ROOT):]
#return redirect(url)
return HttpFileResponse(path, content_type=content_type)