diff video.py @ 15:53d99454f394

support dropping url or file
author drewp@bigasterisk.com
date Sat, 15 Apr 2023 17:23:03 -0700
parents ccfea3625cf6
children 071943adf000
line wrap: on
line diff
--- a/video.py	Sat Apr 15 16:12:26 2023 -0700
+++ b/video.py	Sat Apr 15 17:23:03 2023 -0700
@@ -1,72 +1,20 @@
-import asyncio
-from dataclasses import dataclass
+import logging
 from pathlib import Path
-import hashlib
-import logging
-import re
-from typing import Iterable
 
 from prometheus_client import Gauge
 from starlette.applications import Starlette
 from starlette.requests import Request
-from starlette.responses import HTMLResponse, JSONResponse
+from starlette.responses import HTMLResponse, JSONResponse, Response
 from starlette.routing import Route
 from starlette_exporter import PrometheusMiddleware, handle_metrics
+from sse_starlette.sse import EventSourceResponse
 
-from video_service import VideoFile
+from video_file_store import VideoFileStore
+from video_ingest import VideoIngest
 
 logging.basicConfig(level=logging.DEBUG)
 log = logging.getLogger()
 
-def vf(p: Path, label: str):
-    return VideoFile(p, './files/' + str(p.relative_to('/data')), label)
-
-def thumbWebPath(rel: str)->str:
-    return './files/' + rel
-
-@dataclass
-class VideoFileStore:
-    top: Path
-
-    def findInDir(self, subdir: str) -> Iterable[VideoFile]:
-        if subdir[0] != '/': raise ValueError
-        here = self.top / subdir[1:]
-        manifests = list(here.glob('*.mpd'))
-        if manifests:
-            p = manifests[0]
-            label = p.parent.name
-            yield vf(p, label)
-            return
-        for p in sorted(list(here.glob('*.mp4')) + list(here.glob('*.webm'))):
-            label = re.sub(r' \[[^\]]+\]\.\w+', '', p.name)
-            yield vf(p, label)
-
-
-    def findSubdirs(self, subdir: str) -> Iterable:
-        if subdir[0] != '/': raise ValueError
-        here = self.top / subdir[1:]
-        for p in here.iterdir():
-            if p.is_dir() and p.name not in {'_thumb'}:
-                yield {'label': p.name, 'path': '/' + str(p.relative_to(self.top))}
-
-    def thumbPath(self,  vf: VideoFile) -> str:
-        sha256 = hashlib.sha256()       
-        with open(vf.diskPath, 'rb') as f:
-            firstMb = f.read(1<<20)
-            sha256.update(firstMb)
-        cksum = sha256.hexdigest()
-        return f'_thumb/{cksum}.jpg'
-
-    async def getOrCreateThumb(self, vf: VideoFile) -> str:
-        p = self.top / self.thumbPath(vf)
-        if not p.exists():
-            sp = asyncio.create_subprocess_exec('ffmpegthumbnailer',
-            '-s', '250',
-            '-i', str(vf.diskPath),
-            '-o', str(p))
-            await sp
-        return thumbWebPath(str(p.relative_to(self.top)))
-
 
 def root(req):
     return HTMLResponse("api")
@@ -85,16 +33,46 @@
         list(store.findSubdirs(subdir)),
     })
 
+
+async def ingestVideoUrl(req: Request) -> Response:
+    url = await req.body()
+    svc.ingestUrl(url)
+    return Response(status_code=202)
+
+
+async def ingestVideoUpload(req: Request) -> Response:
+    name = req.query_params['name']
+    await svc.addContent(name, req.body())
+    return Response(status_code=200)
+
+
+async def ingestQueue(req: Request) -> EventSourceResponse:
+
+    def convertEvents(svcEvents):
+        for ev in svcEvents:
+            yield dict(type='ev')
+
+    return EventSourceResponse(convertEvents(svc.events()))
+
+
 store = VideoFileStore(top=Path('/data'))
+svc = VideoIngest(store)
+
 
 def main():
 
-
     app = Starlette(
         debug=True,
         routes=[
             Route('/video/api/', root),
             Route('/video/api/videos', videos),
+            Route('/video/api/ingest/videoUpload',
+                  ingestVideoUpload,
+                  methods=['POST']),
+            Route('/video/api/ingest/videoUrl',
+                  ingestVideoUrl,
+                  methods=['POST']),
+            Route('/video/api/ingest/queue', ingestQueue),
         ],
     )