support merged download for specific resolution,format fixes #2353

This commit is contained in:
j 2014-03-08 11:18:12 +00:00
parent 6b58767d31
commit c055c220e2
3 changed files with 50 additions and 62 deletions

View file

@ -2,15 +2,16 @@
# vi:si:et:sw=4:sts=4:ts=4 # vi:si:et:sw=4:sts=4:ts=4
from __future__ import division, with_statement from __future__ import division, with_statement
from datetime import datetime
import os.path
import subprocess
from glob import glob
import shutil
import uuid
import unicodedata
from urllib import quote
import json import json
import os
import shutil
import subprocess
import tempfile
import unicodedata
import uuid
from datetime import datetime
from glob import glob
from urllib import quote
from django.db import models, transaction from django.db import models, transaction
from django.db.models import Q, Sum, Max from django.db.models import Q, Sum, Max
@ -451,6 +452,30 @@ class Item(models.Model):
other.save() other.save()
#FIXME: update poster, stills and streams after this #FIXME: update poster, stills and streams after this
def merge_streams(self, output, resolution=None, format="webm"):
streams = [s.get(resolution, format).media.path for s in self.streams()]
if len(streams) > 1:
if format == "webm":
first = True
cmd = ['mkvmerge', '-o', output]
cmd += [streams[0]] + ['+' + s for s in streams[1:]]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p.wait()
return True
elif format == "mp4":
fd, tmp_output = tempfile.mkstemp('.mp4')
shutil.copy(streams[0], tmp_output)
for s in streams[1:]:
cmd = ['MP4Box', '-cat', s, tmp_output]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p.wait()
shutil.copy(tmp_output, output)
os.unlink(tmp_output)
return True
else:
return None
return streams[0] if streams else None
def get_posters(self): def get_posters(self):
url = self.prefered_poster_url() url = self.prefered_poster_url()
external_posters = self.external_data.get('posters', {}) external_posters = self.external_data.get('posters', {})
@ -1191,18 +1216,6 @@ class Item(models.Model):
Q(file__is_audio=True)|Q(file__is_video=True) Q(file__is_audio=True)|Q(file__is_video=True)
).order_by('file__part', 'file__sort_path') ).order_by('file__part', 'file__sort_path')
def merge_streams(self, output):
first = True
cmd = ['mkvmerge', '-o', output]
streams = [s.media.path for s in self.streams()]
if len(streams) > 1:
cmd += [streams[0]] + ['+' + s for s in streams[1:]]
print cmd
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p.wait()
return True
return streams[0] if streams else None
def update_timeline(self, force=False, async=True): def update_timeline(self, force=False, async=True):
streams = self.streams() streams = self.streams()
self.make_timeline() self.make_timeline()

View file

@ -12,6 +12,11 @@ urlpatterns = patterns("item.views",
(r'^(?P<id>[A-Z0-9].*)/timeline(?P<mode>[a-z]*)(?P<size>\d+)p(?P<position>\d+)\.(?P<format>png|jpg)$', 'timeline'), (r'^(?P<id>[A-Z0-9].*)/timeline(?P<mode>[a-z]*)(?P<size>\d+)p(?P<position>\d+)\.(?P<format>png|jpg)$', 'timeline'),
(r'^(?P<id>[A-Z0-9].*)/timeline(?P<mode>[a-z]*)(?P<size>\d+)p\.(?P<format>png|jpg)$', 'timeline'), (r'^(?P<id>[A-Z0-9].*)/timeline(?P<mode>[a-z]*)(?P<size>\d+)p\.(?P<format>png|jpg)$', 'timeline'),
#download
(r'^(?P<id>[A-Z0-9].*)/download$', 'download'),
(r'^(?P<id>[A-Z0-9].*)/download/$', 'download'),
(r'^(?P<id>[A-Z0-9].*)/download/(?P<resolution>\d+)p\.(?P<format>webm|ogv|mp4)$', 'download'),
#video #video
(r'^(?P<id>[A-Z0-9].*)/(?P<resolution>\d+)p(?P<index>\d*)\.(?P<format>webm|ogv|mp4)$', 'video'), (r'^(?P<id>[A-Z0-9].*)/(?P<resolution>\d+)p(?P<index>\d*)\.(?P<format>webm|ogv|mp4)$', 'video'),
@ -19,9 +24,6 @@ urlpatterns = patterns("item.views",
(r'^(?P<id>[A-Z0-9].*)/torrent$', 'torrent'), (r'^(?P<id>[A-Z0-9].*)/torrent$', 'torrent'),
(r'^(?P<id>[A-Z0-9].*)/torrent/(?P<filename>.*?)$', 'torrent'), (r'^(?P<id>[A-Z0-9].*)/torrent/(?P<filename>.*?)$', 'torrent'),
#download
(r'^(?P<id>[A-Z0-9].*)/download/$', 'download'),
#export #export
(r'^(?P<id>[A-Z0-9].*)/json$', 'item_json'), (r'^(?P<id>[A-Z0-9].*)/json$', 'item_json'),
(r'^(?P<id>[A-Z0-9].*)/xml$', 'item_xml'), (r'^(?P<id>[A-Z0-9].*)/xml$', 'item_xml'),

View file

@ -840,51 +840,24 @@ def timeline(request, id, size, position=-1, format='jpg', mode=None):
response.allow_access() response.allow_access()
return response return response
def download(request, id, index=1): def download(request, id, resolution=None, format='webm'):
print 'download', id, resolution, format
item = get_object_or_404(models.Item, itemId=id) item = get_object_or_404(models.Item, itemId=id)
if not resolution or int(resolution) not in settings.CONFIG['video']['resolutions']:
resolution = max(settings.CONFIG['video']['resolutions']) resolution = max(settings.CONFIG['video']['resolutions'])
format = 'webm'
if not item.access(request.user):
return HttpResponseForbidden()
if index:
index = int(index) - 1
else: else:
index = 0 resolution = int(resolution)
streams = item.streams()
if index + 1 > streams.count():
raise Http404
stream = streams[index].get(resolution, format)
if not stream.available or not stream.media:
raise Http404
path = stream.media.path
content_type = mimetypes.guess_type(path)[0]
ext = os.path.splitext(path)[-1]
filename = "%s - %s %s%s" % (
item.get('title'),
settings.SITENAME,
item.itemId,
ext
)
response = HttpFileResponse(path, content_type=content_type)
response['Content-Disposition'] = "attachment; filename*=UTF-8''%s" % quote(filename.encode('utf-8'))
return response
def download(request, id):
item = get_object_or_404(models.Item, itemId=id)
resolution = max(settings.CONFIG['video']['resolutions'])
if not item.access(request.user) or not item.rendered: if not item.access(request.user) or not item.rendered:
return HttpResponseForbidden() return HttpResponseForbidden()
ext = '.webm' ext = '.%s' % format
filename = "%s - %s %s%s" % ( parts = ['%s - %s ' % (item.get('title'), settings.SITENAME), item.itemId]
item.get('title'), if resolution != max(settings.CONFIG['video']['resolutions']):
settings.SITENAME, parts.append('.%dp' % resolution)
item.itemId, parts.append(ext)
ext filename = ''.join(parts)
)
video = NamedTemporaryFile(suffix=ext) video = NamedTemporaryFile(suffix=ext)
content_type = mimetypes.guess_type(video.name)[0] content_type = mimetypes.guess_type(video.name)[0]
r = item.merge_streams(video.name) r = item.merge_streams(video.name, resolution, format)
if not r: if not r:
return HttpResponseForbidden() return HttpResponseForbidden()
elif r == True: elif r == True: