Mercurial > code > home > repos > video
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), ], )