]> git.parisson.com Git - timeside.git/commitdiff
Server: add support for streaming transcoded media files
authorThomas Fillon <thomas@parisson.com>
Tue, 2 Dec 2014 15:12:28 +0000 (16:12 +0100)
committerThomas Fillon <thomas@parisson.com>
Tue, 2 Dec 2014 15:12:28 +0000 (16:12 +0100)
timeside/server/models.py
timeside/server/views.py

index 2d36944467d09459c4b578caf212da8f16511780..21558f742d1b50eed429dda87d2c9ddb1ee1542e 100644 (file)
@@ -267,7 +267,7 @@ class Task(BaseResource):
         self.status = status
         self.save()
 
-    def run(self):
+    def run(self, streaming=False):
         self.status_setter(_RUNNING)
 
         results_root = 'results'
@@ -293,7 +293,8 @@ class Task(BaseResource):
                                            proc.file_extension()])
                     result.file = os.path.join(item_path, media_file)
                     result.save()
-                    proc = proc(result.file.path, overwrite=True)
+                    proc = proc(result.file.path, overwrite=True,
+                                streaming=streaming)
                 else:
                     proc = proc()
                 if proc.type == 'analyzer':
@@ -308,7 +309,11 @@ class Task(BaseResource):
                 hdf5_file = str(self.experience.uuid) + '.hdf5'
                 item.hdf5 = os.path.join(item_path, hdf5_file)
                 item.save()
-            pipe.run()
+            if streaming:
+                for chunk in pipe.stream():
+                    yield chunk
+            else:
+                pipe.run()
             item.lock_setter(True)
             #pipe.results.to_hdf5(item.hdf5.path)
 
index d77ad691e9470e7d866e09f90502a633a7762c9c..4cc4578c84d0d1ef68a8d1f96f3a004c972a39bf 100644 (file)
 from django.http import Http404
 from django.views.generic.base import View
 from django.views.generic import DetailView, ListView
-from django.views.generic.detail import SingleObjectMixin
-from django.http import HttpResponse
+from django.http import HttpResponse, StreamingHttpResponse
 
 from rest_framework import viewsets
 
 from timeside.server.models import Experience, Item, Result, Processor
 from timeside.server.models import Preset, Selection, Task, User
-from timeside.server.models import _PENDING
+from timeside.server.models import _DRAFT
 from timeside.server.serializers import ExperienceSerializer, ItemSerializer
 from timeside.server.serializers import PresetSerializer
 from timeside.server.serializers import ProcessorSerializer
@@ -40,6 +39,7 @@ from timeside.server.serializers import SelectionSerializer
 from timeside.server.serializers import TaskSerializer
 from timeside.server.serializers import UserSerializer
 
+import timeside.core
 from timeside.analyzer.core import AnalyzerResultContainer
 import os
 
@@ -55,6 +55,12 @@ def stream_from_file(file):
         yield chunk
 
 
+def stream_from_task(task):
+    for chunk in task.run(streaming=True):
+        yield chunk
+    task.save()
+
+
 class SelectionViewSet(viewsets.ModelViewSet):
 
     model = Selection
@@ -153,7 +159,7 @@ class ItemDetail(DetailView):
     template_name = 'timeside/item_detail.html'
 
 
-class ItemExport(DetailView, SingleObjectMixin):
+class ItemExport(DetailView):
     model = Item
 
     def get(self, request, pk, extension):
@@ -163,6 +169,7 @@ class ItemExport(DetailView, SingleObjectMixin):
             raise Http404('Unknown export file extension: %s' % extension)
 
         encoder = TS_ENCODERS_EXT[extension]
+        mime_type = timeside.core.get_processor(encoder).mime_type()
         # Get or Create Processor = encoder
         processor, created = Processor.objects.get_or_create(pid=encoder)
         # Get or Create Preset with processor
@@ -172,21 +179,41 @@ class ItemExport(DetailView, SingleObjectMixin):
         try:
             result = Result.objects.get(item=item, preset=preset)
             if not os.path.exists(result.file.path):
+                # Result exists but not file (may have been deleted)
                 result.delete()
                 return self.get(request, pk, extension)
+            # Result and file exist --> OK
             return HttpResponse(stream_from_file(result.file.path),
-                                mimetype=result.mime_type)
+                                content_type=result.mime_type)
         except Result.DoesNotExist:
             # Result does not exist
             # the corresponding task has to be created and run
-            experience = Experience()
-            experience.save()
-            experience.presets.add(preset)
-            selection = Selection()
-            selection.save()
-            selection.items.add(item)
+            exp_title = "Transcode to %s" % extension
+            exp_description = ("Experience for transcoding an item to %s\n"
+                               "Automatically generated by the TimeSide "
+                               "application.") % mime_type
+            experience, created = Experience.objects.get_or_create(
+                title=exp_title,
+                description=exp_description)
+            if created:
+                experience.save()
+                experience.presets.add(preset)
+
+            sel_title = "Singleton selection for item %d" % item.id
+            sel_description = ("Singleton selection for item %d\n"
+                               "Automatically generated by the TimeSide "
+                               "application.") % item.id
+            selection, created = Selection.objects.get_or_create(
+                title=sel_title,
+                description=sel_description)
+            if created:
+                selection.save()
+                selection.items.add(item)
             task = Task(experience=experience, selection=selection,
-                        status=_PENDING)
-            task.save()  # save task and run
-            # TODO : find a way to stream during task ...
-            return self.get(request, pk, extension)
+                        status=_DRAFT)
+            task.save()
+            # Run task in streaming mode
+            response = StreamingHttpResponse()
+            response['streaming_content'] = task.run(streaming=True)
+            response['content-type'] = mime_type
+            return response