Skip to content

Instantly share code, notes, and snippets.

@Wurushu
Created February 24, 2025 10:47
Show Gist options
  • Save Wurushu/f57efe1d0329746b50c68a995a4247f3 to your computer and use it in GitHub Desktop.
Save Wurushu/f57efe1d0329746b50c68a995a4247f3 to your computer and use it in GitHub Desktop.
A simple HTTP server (video streaming support) with Python
#!/usr/bin/env python3
import sys
import os
from http.server import SimpleHTTPRequestHandler, CGIHTTPRequestHandler, HTTPServer
class VideoHTTPRequestHandler(SimpleHTTPRequestHandler):
def do_GET(self):
"""Handle GET request, supporting video streaming (Range Requests)."""
if self.path.startswith('/test_folder/') and self.path.endswith('.mp4'): # 只對 /test_folder/ 目錄下的 mp4 檔案處理
file_path = "." + self.path
if not os.path.exists(file_path):
self.send_error(404, "File Not Found")
return
file_size = os.path.getsize(file_path)
range_header = self.headers.get("Range")
range_start = 0
range_end = min(range_start + 1024 * 1024, file_size - 1) # 預設回傳整個影片大小或1M
if range_header:
# 處理 Range 請求
range_parts = range_header.split("=")[1].split("-")
range_start = int(range_parts[0]) if range_parts[0] else 0
range_end = int(range_parts[1]) if len(range_parts) > 1 and range_parts[1] else min(range_start + 1024 * 1024, file_size - 1) # 預設回傳整個影片大小或1M
# 檢查 range 跟 size
if range_start < 0 or range_end >= file_size or range_start > range_end:
self.send_error(416, "Requested Range Not Satisfiable")
return
print(f"Stream video, bytes={range_start}-{range_end} of {file_size}")
self.send_response(206) # 206 Partial Content
self.send_header("Content-Type", "video/mp4")
self.send_header("Content-Length", str(range_end - range_start + 1))
self.send_header("Accept-Ranges", "bytes")
self.send_header("Content-Range", f"bytes {range_start}-{range_end}/{file_size}")
self.end_headers()
with open(file_path, "rb") as f:
f.seek(range_start)
chunk_size = 64 * 1024 # 64 KB
bytes_sent = 0
while bytes_sent <= (range_end - range_start):
data = f.read(min(chunk_size, (range_end - range_start + 1) - bytes_sent))
if not data:
break
self.wfile.write(data)
self.wfile.flush() # 確保立即發送
bytes_sent += len(data)
else:
# 如果不是影片,使用原本的 SimpleHTTPRequestHandler 處理
super().do_GET()
def serve_forever(host, port):
print(sys.version_info)
# handler = CGIHTTPRequestHandler
server = HTTPServer((host, port), VideoHTTPRequestHandler)
print ('Server started ({}, {})'.format(host, port))
server.serve_forever()
if __name__ == '__main__':
serve_forever('0.0.0.0', 8440)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment