Mercurial > code > home > repos > video
annotate video.py @ 37:7cacfae58430
thumbnails rewrite - store in db; don't use YT-provided pics for now
author | drewp@bigasterisk.com |
---|---|
date | Tue, 03 Dec 2024 19:28:11 -0800 |
parents | ed16fdbb3996 |
children | 0aea9e55899b |
rev | line source |
---|---|
17
071943adf000
dnd a file or a url which we'll queue and fetch
drewp@bigasterisk.com
parents:
15
diff
changeset
|
1 import asyncio |
37
7cacfae58430
thumbnails rewrite - store in db; don't use YT-provided pics for now
drewp@bigasterisk.com
parents:
36
diff
changeset
|
2 from functools import partial |
17
071943adf000
dnd a file or a url which we'll queue and fetch
drewp@bigasterisk.com
parents:
15
diff
changeset
|
3 import json |
15 | 4 import logging |
5
75b54be050bc
show one subdir of archive at once, with folders and parents-breadcrumbs
drewp@bigasterisk.com
parents:
4
diff
changeset
|
5 |
28
1e058bea3ac2
crash better when mongo is unreachable
drewp@bigasterisk.com
parents:
27
diff
changeset
|
6 import uvicorn |
3 | 7 from prometheus_client import Gauge |
28
1e058bea3ac2
crash better when mongo is unreachable
drewp@bigasterisk.com
parents:
27
diff
changeset
|
8 from sse_starlette.sse import EventSourceResponse |
3 | 9 from starlette.applications import Starlette |
10 from starlette.requests import Request | |
15 | 11 from starlette.responses import HTMLResponse, JSONResponse, Response |
3 | 12 from starlette.routing import Route |
13 from starlette_exporter import PrometheusMiddleware, handle_metrics | |
5
75b54be050bc
show one subdir of archive at once, with folders and parents-breadcrumbs
drewp@bigasterisk.com
parents:
4
diff
changeset
|
14 |
28
1e058bea3ac2
crash better when mongo is unreachable
drewp@bigasterisk.com
parents:
27
diff
changeset
|
15 import dl_queue |
15 | 16 from video_file_store import VideoFileStore |
17 from video_ingest import VideoIngest | |
36
ed16fdbb3996
rewrite WIP. scan fs separately; store in db. thumbs are broken for now
drewp@bigasterisk.com
parents:
32
diff
changeset
|
18 from mongo_required import open_mongo_or_die |
37
7cacfae58430
thumbnails rewrite - store in db; don't use YT-provided pics for now
drewp@bigasterisk.com
parents:
36
diff
changeset
|
19 import pymongo.database |
7cacfae58430
thumbnails rewrite - store in db; don't use YT-provided pics for now
drewp@bigasterisk.com
parents:
36
diff
changeset
|
20 import thumbnail |
18 | 21 |
3 | 22 logging.basicConfig(level=logging.DEBUG) |
23 log = logging.getLogger() | |
17
071943adf000
dnd a file or a url which we'll queue and fetch
drewp@bigasterisk.com
parents:
15
diff
changeset
|
24 logging.getLogger('sse_starlette').setLevel(logging.WARNING) |
32 | 25 logging.getLogger('pymongo').setLevel(logging.INFO) |
0 | 26 |
27 | |
3 | 28 def root(req): |
29 return HTMLResponse("api") | |
0 | 30 |
31 | |
6
ccfea3625cf6
render thumbs and display them (no video player at all atm)
drewp@bigasterisk.com
parents:
5
diff
changeset
|
32 async def videos(req: Request) -> JSONResponse: |
5
75b54be050bc
show one subdir of archive at once, with folders and parents-breadcrumbs
drewp@bigasterisk.com
parents:
4
diff
changeset
|
33 subdir = req.query_params.get('subdir', '/') # danger user input |
6
ccfea3625cf6
render thumbs and display them (no video player at all atm)
drewp@bigasterisk.com
parents:
5
diff
changeset
|
34 vfInDir = store.findInDir(subdir) |
4
c8a41359505c
server provides video listing from disk
drewp@bigasterisk.com
parents:
3
diff
changeset
|
35 return JSONResponse({ |
c8a41359505c
server provides video listing from disk
drewp@bigasterisk.com
parents:
3
diff
changeset
|
36 "videos": [{ |
c8a41359505c
server provides video listing from disk
drewp@bigasterisk.com
parents:
3
diff
changeset
|
37 'webRelPath': vf.webRelPath, |
36
ed16fdbb3996
rewrite WIP. scan fs separately; store in db. thumbs are broken for now
drewp@bigasterisk.com
parents:
32
diff
changeset
|
38 'webDataPath': vf.webDataPath, |
4
c8a41359505c
server provides video listing from disk
drewp@bigasterisk.com
parents:
3
diff
changeset
|
39 'label': vf.label, |
6
ccfea3625cf6
render thumbs and display them (no video player at all atm)
drewp@bigasterisk.com
parents:
5
diff
changeset
|
40 } for vf in vfInDir], |
5
75b54be050bc
show one subdir of archive at once, with folders and parents-breadcrumbs
drewp@bigasterisk.com
parents:
4
diff
changeset
|
41 "subdirs": |
6
ccfea3625cf6
render thumbs and display them (no video player at all atm)
drewp@bigasterisk.com
parents:
5
diff
changeset
|
42 list(store.findSubdirs(subdir)), |
4
c8a41359505c
server provides video listing from disk
drewp@bigasterisk.com
parents:
3
diff
changeset
|
43 }) |
c8a41359505c
server provides video listing from disk
drewp@bigasterisk.com
parents:
3
diff
changeset
|
44 |
15 | 45 |
20 | 46 def folderTree(req: Request) -> JSONResponse: |
47 return JSONResponse(store.folderTree()) | |
48 | |
49 | |
15 | 50 async def ingestVideoUrl(req: Request) -> Response: |
23
9e56e86a6814
server supports downloading into a given folder
drewp@bigasterisk.com
parents:
20
diff
changeset
|
51 folder = req.query_params['folder'] |
15 | 52 url = await req.body() |
23
9e56e86a6814
server supports downloading into a given folder
drewp@bigasterisk.com
parents:
20
diff
changeset
|
53 await svc.ingestUrl(url.decode('utf8'), folder) |
15 | 54 return Response(status_code=202) |
55 | |
56 | |
57 async def ingestVideoUpload(req: Request) -> Response: | |
58 name = req.query_params['name'] | |
59 await svc.addContent(name, req.body()) | |
60 return Response(status_code=200) | |
61 | |
62 | |
63 async def ingestQueue(req: Request) -> EventSourceResponse: | |
18 | 64 |
17
071943adf000
dnd a file or a url which we'll queue and fetch
drewp@bigasterisk.com
parents:
15
diff
changeset
|
65 async def g(): |
071943adf000
dnd a file or a url which we'll queue and fetch
drewp@bigasterisk.com
parents:
15
diff
changeset
|
66 async for ev in svc.events(): |
071943adf000
dnd a file or a url which we'll queue and fetch
drewp@bigasterisk.com
parents:
15
diff
changeset
|
67 yield json.dumps(ev) |
18 | 68 |
17
071943adf000
dnd a file or a url which we'll queue and fetch
drewp@bigasterisk.com
parents:
15
diff
changeset
|
69 return EventSourceResponse(g()) |
15 | 70 |
37
7cacfae58430
thumbnails rewrite - store in db; don't use YT-provided pics for now
drewp@bigasterisk.com
parents:
36
diff
changeset
|
71 def getDiskPath(fs, webRelPath): |
7cacfae58430
thumbnails rewrite - store in db; don't use YT-provided pics for now
drewp@bigasterisk.com
parents:
36
diff
changeset
|
72 doc = fs.find_one({'webRelPath': webRelPath}) |
7cacfae58430
thumbnails rewrite - store in db; don't use YT-provided pics for now
drewp@bigasterisk.com
parents:
36
diff
changeset
|
73 if doc is None: |
7cacfae58430
thumbnails rewrite - store in db; don't use YT-provided pics for now
drewp@bigasterisk.com
parents:
36
diff
changeset
|
74 raise ValueError |
7cacfae58430
thumbnails rewrite - store in db; don't use YT-provided pics for now
drewp@bigasterisk.com
parents:
36
diff
changeset
|
75 return doc['diskPath'] |
7cacfae58430
thumbnails rewrite - store in db; don't use YT-provided pics for now
drewp@bigasterisk.com
parents:
36
diff
changeset
|
76 |
7cacfae58430
thumbnails rewrite - store in db; don't use YT-provided pics for now
drewp@bigasterisk.com
parents:
36
diff
changeset
|
77 async def getThumbnail(db: pymongo.database.Database, req: Request) -> Response: |
7cacfae58430
thumbnails rewrite - store in db; don't use YT-provided pics for now
drewp@bigasterisk.com
parents:
36
diff
changeset
|
78 webRelPath = req.query_params['webRelPath'] |
7cacfae58430
thumbnails rewrite - store in db; don't use YT-provided pics for now
drewp@bigasterisk.com
parents:
36
diff
changeset
|
79 fs = db.get_collection('fs') |
7cacfae58430
thumbnails rewrite - store in db; don't use YT-provided pics for now
drewp@bigasterisk.com
parents:
36
diff
changeset
|
80 diskPath = getDiskPath(fs, webRelPath) |
7cacfae58430
thumbnails rewrite - store in db; don't use YT-provided pics for now
drewp@bigasterisk.com
parents:
36
diff
changeset
|
81 th = db.get_collection('thumb') |
7cacfae58430
thumbnails rewrite - store in db; don't use YT-provided pics for now
drewp@bigasterisk.com
parents:
36
diff
changeset
|
82 async with asyncio.timeout(10): |
7cacfae58430
thumbnails rewrite - store in db; don't use YT-provided pics for now
drewp@bigasterisk.com
parents:
36
diff
changeset
|
83 data = await thumbnail.getThumbnailData(th, diskPath) |
7cacfae58430
thumbnails rewrite - store in db; don't use YT-provided pics for now
drewp@bigasterisk.com
parents:
36
diff
changeset
|
84 return Response(content=data, media_type='image/jpeg') |
7cacfae58430
thumbnails rewrite - store in db; don't use YT-provided pics for now
drewp@bigasterisk.com
parents:
36
diff
changeset
|
85 |
7cacfae58430
thumbnails rewrite - store in db; don't use YT-provided pics for now
drewp@bigasterisk.com
parents:
36
diff
changeset
|
86 |
15 | 87 |
36
ed16fdbb3996
rewrite WIP. scan fs separately; store in db. thumbs are broken for now
drewp@bigasterisk.com
parents:
32
diff
changeset
|
88 db = open_mongo_or_die().get_database('video') |
ed16fdbb3996
rewrite WIP. scan fs separately; store in db. thumbs are broken for now
drewp@bigasterisk.com
parents:
32
diff
changeset
|
89 store = VideoFileStore(db.get_collection('fs')) |
15 | 90 svc = VideoIngest(store) |
91 | |
18 | 92 |
4
c8a41359505c
server provides video listing from disk
drewp@bigasterisk.com
parents:
3
diff
changeset
|
93 def main(): |
3 | 94 |
95 app = Starlette( | |
96 debug=True, | |
97 routes=[ | |
4
c8a41359505c
server provides video listing from disk
drewp@bigasterisk.com
parents:
3
diff
changeset
|
98 Route('/video/api/', root), |
c8a41359505c
server provides video listing from disk
drewp@bigasterisk.com
parents:
3
diff
changeset
|
99 Route('/video/api/videos', videos), |
20 | 100 Route('/video/api/folderTree', folderTree), |
15 | 101 Route('/video/api/ingest/videoUpload', |
102 ingestVideoUpload, | |
103 methods=['POST']), | |
104 Route('/video/api/ingest/videoUrl', | |
105 ingestVideoUrl, | |
106 methods=['POST']), | |
107 Route('/video/api/ingest/queue', ingestQueue), | |
37
7cacfae58430
thumbnails rewrite - store in db; don't use YT-provided pics for now
drewp@bigasterisk.com
parents:
36
diff
changeset
|
108 Route('/video/api/thumbnail', partial(getThumbnail, db)), |
3 | 109 ], |
110 ) | |
111 | |
112 app.add_middleware(PrometheusMiddleware, app_name='video_api') | |
25 | 113 app.add_route("/video/api/metrics", handle_metrics) |
27 | 114 app.add_route("/metrics", handle_metrics) |
18 | 115 |
17
071943adf000
dnd a file or a url which we'll queue and fetch
drewp@bigasterisk.com
parents:
15
diff
changeset
|
116 app.state.processTask = asyncio.create_task(dl_queue.process()) |
4
c8a41359505c
server provides video listing from disk
drewp@bigasterisk.com
parents:
3
diff
changeset
|
117 return app |
3 | 118 |
28
1e058bea3ac2
crash better when mongo is unreachable
drewp@bigasterisk.com
parents:
27
diff
changeset
|
119 uvicorn.run(main, |
1e058bea3ac2
crash better when mongo is unreachable
drewp@bigasterisk.com
parents:
27
diff
changeset
|
120 host="0.0.0.0", |
1e058bea3ac2
crash better when mongo is unreachable
drewp@bigasterisk.com
parents:
27
diff
changeset
|
121 port=8004, |
1e058bea3ac2
crash better when mongo is unreachable
drewp@bigasterisk.com
parents:
27
diff
changeset
|
122 log_level=logging.INFO, |
1e058bea3ac2
crash better when mongo is unreachable
drewp@bigasterisk.com
parents:
27
diff
changeset
|
123 factory=True) |