Created
February 24, 2025 10:47
-
-
Save Wurushu/f57efe1d0329746b50c68a995a4247f3 to your computer and use it in GitHub Desktop.
A simple HTTP server (video streaming support) with Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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