neu-denken-analyse/webapp/server.py
Dotty Dotter 3eb4556301 Initial commit: NEU DENKEN Podcast-Analyse
19 Episoden (4 Staffeln), 159 verifizierte Zitate mit Audio-Timestamps,
7 Themenkomplexe, interaktive Mindmap-Webapp.
Nutzt podcast-mindmap als Tool (../podcast-mindmap).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 01:25:59 +02:00

74 lines
2.4 KiB
Python

#!/usr/bin/env python3
"""HTTP server with Range request support for audio streaming."""
import os
from http.server import HTTPServer, SimpleHTTPRequestHandler
MIME_OVERRIDES = {'.m4a': 'audio/mp4', '.srt': 'text/plain'}
class RangeHandler(SimpleHTTPRequestHandler):
def do_GET(self):
path = self.translate_path(self.path)
if not os.path.isfile(path):
return super().do_GET()
range_header = self.headers.get('Range')
file_size = os.path.getsize(path)
ext = os.path.splitext(path)[1].lower()
ctype = MIME_OVERRIDES.get(ext) or self.guess_type(path)
if not range_header:
# Normal response but with Accept-Ranges
self.send_response(200)
self.send_header('Content-Type', ctype)
self.send_header('Content-Length', str(file_size))
self.send_header('Accept-Ranges', 'bytes')
self.send_header('Access-Control-Allow-Origin', '*')
self.end_headers()
with open(path, 'rb') as f:
self.copyfile(f, self.wfile)
return
# Parse range
try:
range_spec = range_header.replace('bytes=', '')
parts = range_spec.split('-')
start = int(parts[0]) if parts[0] else 0
end = int(parts[1]) if parts[1] else file_size - 1
end = min(end, file_size - 1)
length = end - start + 1
except (ValueError, IndexError):
self.send_error(416)
return
self.send_response(206)
self.send_header('Content-Type', ctype)
self.send_header('Content-Range', f'bytes {start}-{end}/{file_size}')
self.send_header('Content-Length', str(length))
self.send_header('Accept-Ranges', 'bytes')
self.send_header('Access-Control-Allow-Origin', '*')
self.end_headers()
with open(path, 'rb') as f:
f.seek(start)
remaining = length
buf_size = 65536
while remaining > 0:
chunk = f.read(min(buf_size, remaining))
if not chunk:
break
self.wfile.write(chunk)
remaining -= len(chunk)
def end_headers(self):
# Don't double-add Accept-Ranges
super().end_headers()
if __name__ == '__main__':
port = 9123
print(f"http://0.0.0.0:{port}")
HTTPServer(('0.0.0.0', port), RangeHandler).serve_forever()