backup
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
"""Local server: serves clip-browser.html + handles POST /build-reel to run ffmpeg."""
|
||||
import http.server, json, os, subprocess, urllib.parse
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
|
||||
VID_DIR = os.path.join(BASE_DIR, "assets", "videos", "hero", "clips")
|
||||
REEL_OUT = os.path.join(BASE_DIR, "assets", "videos", "hero", "hero-reel.mp4")
|
||||
TOOLS_DIR = os.path.dirname(__file__)
|
||||
|
||||
class Handler(http.server.BaseHTTPRequestHandler):
|
||||
def log_message(self, fmt, *args): pass
|
||||
|
||||
def do_GET(self):
|
||||
path = self.path.split('?')[0]
|
||||
if path in ('/', '/tools/clip-browser.html'):
|
||||
self._serve_file(os.path.join(TOOLS_DIR, 'clip-browser.html'), 'text/html')
|
||||
elif path.startswith('/assets/videos/'):
|
||||
rel = path.lstrip('/')
|
||||
fpath = os.path.join(BASE_DIR, rel)
|
||||
if os.path.exists(fpath):
|
||||
self._serve_file(fpath, 'video/mp4')
|
||||
else:
|
||||
self._404()
|
||||
else:
|
||||
self._404()
|
||||
|
||||
def do_POST(self):
|
||||
if self.path == '/tools/build-reel-api.py':
|
||||
length = int(self.headers.get('Content-Length', 0))
|
||||
body = json.loads(self.rfile.read(length))
|
||||
clips = body.get('clips', [])
|
||||
if not clips:
|
||||
self._json({'message': 'No clips provided.'}, 400)
|
||||
return
|
||||
concat_file = os.path.join(VID_DIR, 'concat-browser.txt')
|
||||
missing = []
|
||||
with open(concat_file, 'w') as f:
|
||||
for name in clips:
|
||||
p = os.path.join(VID_DIR, f'{name}.mp4')
|
||||
if not os.path.exists(p):
|
||||
missing.append(name)
|
||||
else:
|
||||
f.write(f"file '{p}'\n")
|
||||
if missing:
|
||||
self._json({'message': f'Missing clips: {missing}'}, 400)
|
||||
return
|
||||
result = subprocess.run(
|
||||
['ffmpeg', '-y', '-f', 'concat', '-safe', '0', '-i', concat_file,
|
||||
'-c:v', 'libx264', '-crf', '22', '-preset', 'fast',
|
||||
'-movflags', '+faststart', REEL_OUT],
|
||||
capture_output=True, text=True
|
||||
)
|
||||
if result.returncode == 0:
|
||||
size = os.path.getsize(REEL_OUT) // 1024
|
||||
self._json({'message': f'Reel built: hero-reel.mp4 ({size}KB). Now rebuild Docker: docker compose up -d --build'})
|
||||
else:
|
||||
self._json({'message': f'ffmpeg error: {result.stderr[-300:]}'}, 500)
|
||||
else:
|
||||
self._404()
|
||||
|
||||
def _serve_file(self, path, ctype):
|
||||
with open(path, 'rb') as f:
|
||||
data = f.read()
|
||||
self.send_response(200)
|
||||
self.send_header('Content-Type', ctype)
|
||||
self.send_header('Content-Length', len(data))
|
||||
self.end_headers()
|
||||
self.wfile.write(data)
|
||||
|
||||
def _json(self, obj, code=200):
|
||||
data = json.dumps(obj).encode()
|
||||
self.send_response(code)
|
||||
self.send_header('Content-Type', 'application/json')
|
||||
self.send_header('Content-Length', len(data))
|
||||
self.end_headers()
|
||||
self.wfile.write(data)
|
||||
|
||||
def _404(self):
|
||||
self.send_response(404)
|
||||
self.end_headers()
|
||||
|
||||
if __name__ == '__main__':
|
||||
port = 8088
|
||||
print(f'Clip browser running at http://localhost:{port}/')
|
||||
http.server.HTTPServer(('', port), Handler).serve_forever()
|
||||
Reference in New Issue
Block a user