antv-live / run.py
ken1402's picture
Update run.py
0a82fca verified
Raw
History Blame Contribute Delete
4.89 kB
import os
import sys
import time
import subprocess
import threading
import http.server
import socketserver
# ==============================================================================
# CẤU HÌNH HỆ THỐNG GỐC CHUẨN ANTV-LIVE TRÊN HUGGING FACE SPACES
# ==============================================================================
INPUT_STREAM = "http://10k.lucastv.pro/2c99755ae255/gJnMAT2/465825"
OUTPUT_DIR = "/app/output_hls"
PORT = 7860
HTTP_HEADERS = (
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36\r\n"
"Referer: https://xeno.env.pm/\r\n"
)
LOCAL_LOGO_TARGET = "/tmp/real_uhd.png"
print("=== [1/4] Khởi tạo thư mục đầu ra HLS ===", flush=True)
for folder in ["720p30", "720p50", "1080p30", "1080p50"]:
os.makedirs(os.path.join(OUTPUT_DIR, folder), exist_ok=True)
# Tạo sẵn file master.m3u8 giả lập chống lỗi 404/503 ngay từ giây đầu tiên
placeholder_master = """#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=1500000,RESOLUTION=1280x720
720p30/playlist.m3u8
"""
with open(os.path.join(OUTPUT_DIR, "master.m3u8"), "w") as f:
f.write(placeholder_master)
print("=== [2/4] Kích hoạt Python HTTP Server trên cổng 7860 (Ngăn triệt để lỗi 503) ===", flush=True)
def start_web_server():
os.chdir(OUTPUT_DIR)
Handler = http.server.SimpleHTTPRequestHandler
socketserver.TCPServer.allow_reuse_address = True
with socketserver.TCPServer(("", PORT), Handler) as httpd:
print(f"-> HTTP Server đang lắng nghe trên cổng {PORT}", flush=True)
httpd.serve_forever()
server_thread = threading.Thread(target=start_web_server, daemon=True)
server_thread.start()
time.sleep(1)
print("=== [3/4] Kiểm tra và chuẩn bị tài nguyên logo ===", flush=True)
if os.path.exists("/app/logo1.png"):
LOCAL_LOGO_TARGET = "/app/logo1.png"
print("-> Sử dụng /app/logo1.png sẵn có.", flush=True)
else:
subprocess.run([
"ffmpeg", "-f", "lavfi", "-i", "color=c=black@0:s=1920x1080",
"-vframes", "1", LOCAL_LOGO_TARGET, "-y"
], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
print("-> Đã tạo canvas logo dự phòng.", flush=True)
print("=== [4/4] Khởi chạy tiến trình FFmpeg Transcode đa luồng thích ứng ===", flush=True)
ffmpeg_cmd = [
"ffmpeg", "-y", "-re",
"-fflags", "+genpts+igndts+discardcorrupt",
"-probesize", "2000000",
"-analyzeduration", "2000000",
"-headers", HTTP_HEADERS,
"-reconnect", "1", "-reconnect_at_eof", "1", "-reconnect_streamed", "1", "-reconnect_delay_max", "5",
"-i", INPUT_STREAM,
"-i", LOCAL_LOGO_TARGET,
"-filter_complex",
"[1:v]scale=3840:-1[scaled_logo];"
"[0:v][scaled_logo]overlay=0:0,format=yuv420p,split=4[v1][v2][v3][v4];"
"[v1]scale=1280:720,fps=30[v720p30];"
"[v2]scale=1280:720,fps=50[v720p50];"
"[v3]scale=1920:1080,fps=30[v1080p30];"
"[v4]scale=1920:1080,fps=50[v1080p50];"
"[0:a]aresample=44100:async=1,pan=stereo|"
"FL=0.5*FL+0.707*FC+0.5*BL+0.5*LFE|"
"FR=0.5*FR+0.707*FC+0.5*BR+0.5*LFE,asplit=4[a1][a2][a3][a4]",
"-map", "[v720p30]", "-map", "[a1]", "-c:v:0", "libx264", "-preset", "ultrafast", "-b:v:0", "1200k", "-maxrate:v:0", "1500k", "-bufsize:v:0", "3000k", "-g:v:0", "60", "-keyint_min:v:0", "60", "-sc_threshold:v:0", "0", "-c:a:0", "aac", "-b:a:0", "128k",
"-map", "[v720p50]", "-map", "[a2]", "-c:v:1", "libx264", "-preset", "ultrafast", "-b:v:1", "1800k", "-maxrate:v:1", "2200k", "-bufsize:v:1", "4500k", "-g:v:1", "100", "-keyint_min:v:1", "100", "-sc_threshold:v:1", "0", "-c:a:1", "aac", "-b:a:1", "128k",
"-map", "[v1080p30]", "-map", "[a3]", "-c:v:2", "libx264", "-preset", "ultrafast", "-b:v:2", "2500k", "-maxrate:v:2", "3000k", "-bufsize:v:2", "6000k", "-g:v:2", "60", "-keyint_min:v:2", "60", "-sc_threshold:v:2", "0", "-c:a:2", "aac", "-b:a:2", "192k",
"-map", "[v1080p50]", "-map", "[a4]", "-c:v:3", "libx264", "-preset", "ultrafast", "-b:v:3", "3500k", "-maxrate:v:3", "4000k", "-bufsize:v:3", "8000k", "-g:v:3", "100", "-keyint_min:v:3", "100", "-sc_threshold:v:3", "0", "-c:a:3", "aac", "-b:a:3", "192k",
"-f", "hls",
"-hls_time", "4",
"-start_number", "0",
"-hls_list_size", "6",
"-hls_flags", "delete_segments+independent_segments",
"-master_pl_name", "master.m3u8",
"-var_stream_map", "v:0,a:0,name:720p30 v:1,a:1,name:720p50 v:2,a:2,name:1080p30 v:3,a:3,name:1080p50",
f"{OUTPUT_DIR}/%v/segment_%05d.ts",
f"{OUTPUT_DIR}/%v/playlist.m3u8"
]
while True:
print("-> Bắt đầu tiến trình FFmpeg Transcode...", flush=True)
process = subprocess.Popen(ffmpeg_cmd)
process.wait()
print(f"-> FFmpeg thoát với mã {process.returncode}. Khởi động lại sau 3 giây...", flush=True)
time.sleep(3)