Mercurial > code > home > repos > video
view video_file_store.py @ 22:ff73b95fc72f
frontend cleanups and improvements. this commit contains some future work too
author | drewp@bigasterisk.com |
---|---|
date | Mon, 17 Apr 2023 13:33:05 -0700 |
parents | cf6842952e13 |
children | ed16fdbb3996 |
line wrap: on
line source
import asyncio import hashlib import re import os from dataclasses import dataclass from pathlib import Path from typing import Iterable, Iterator, NewType IGNORE = {'_thumb'} @dataclass class VideoFile: diskPath: Path webRelPath: str label: str # perms, playlists, req by/when 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 IGNORE: 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))) async def save(self, name: str, chunks: Iterator[bytes]): p = self.top / name if p.exists(): raise ValueError(f'{p} exists') data = b'' for c in chunks: data += c p.write_bytes(data) def folderTree(self): out = {'name': 'TOP'} def fill(node: dict, pathToHere: Path): for subName in sorted(os.listdir(pathToHere)): if subName in IGNORE: continue subDir = pathToHere / subName if subDir.is_dir(): subNode = {'name': subName} node.setdefault('children', []).append(subNode) fill(subNode, subDir) fill(out, self.top) return out