111 lines
6.9 KiB
Plaintext
111 lines
6.9 KiB
Plaintext
|
||
try:
|
||
if split_video_by_time:
|
||
now = time.strftime("%Y-%m-%d_%H-%M-%S", time.localtime())
|
||
print(f"{rec_info} 开始推流到 YouTube: {anchor_name}_{title_in_name}_{now}")
|
||
|
||
YT_STREAM_KEY = "ue78-1c3e-mr9g-14mz-9r4z"
|
||
youtube_rtmp = f"rtmp://a.rtmp.youtube.com/live2/{YT_STREAM_KEY}"
|
||
|
||
# ------------------------
|
||
# NVENC 检测
|
||
# ------------------------
|
||
codec_v = "libx264"
|
||
preset_v = "veryfast"
|
||
tune_param = ["-tune", "zerolatency"]
|
||
|
||
try:
|
||
if platform.system().lower() in ["windows", "linux"]:
|
||
check = subprocess.run(["nvidia-smi"], capture_output=True, timeout=10)
|
||
if check.returncode == 0:
|
||
enc = subprocess.run(["ffmpeg", "-hide_banner", "-encoders"],
|
||
capture_output=True, text=True, timeout=10)
|
||
if "h264_nvenc" in enc.stdout:
|
||
codec_v = "h264_nvenc"
|
||
preset_v = "p5"
|
||
tune_param = ["-tune", "ll", "-rc", "vbr"]
|
||
print("检测到 NVIDIA GPU → 使用 NVENC 硬件加速")
|
||
except:
|
||
pass # 异常自动降级
|
||
|
||
# ------------------------
|
||
# FFmpeg 命令(稳定推流)
|
||
# ------------------------
|
||
ffmpeg_command = [
|
||
"ffmpeg",
|
||
"-re",
|
||
"-i", real_url,
|
||
|
||
"-vf", "scale=720:1280:force_original_aspect_ratio=decrease,pad=720:1280:(ow-iw)/2:(oh-ih)/2:black",
|
||
|
||
"-c:v", codec_v,
|
||
"-preset", preset_v,
|
||
*tune_param,
|
||
|
||
"-b:v", "2500k",
|
||
"-maxrate", "2500k",
|
||
"-bufsize", "5000k",
|
||
"-g", "50",
|
||
"-r", "25",
|
||
"-pix_fmt", "yuv420p",
|
||
"-bf", "0",
|
||
|
||
"-c:a", "aac",
|
||
"-b:a", "128k",
|
||
"-ar", "44100",
|
||
"-ac", "2",
|
||
"-af", "aresample=async=1:first_pts=0",
|
||
|
||
"-flags", "+low_delay",
|
||
"-fflags", "+genpts",
|
||
"-thread_queue_size", "512",
|
||
"-threads", "6",
|
||
|
||
"-f", "flv",
|
||
youtube_rtmp
|
||
]
|
||
|
||
# ------------------------
|
||
# 永不断流重连逻辑
|
||
# ------------------------
|
||
proc = None
|
||
while True:
|
||
try:
|
||
if proc and proc.poll() is None:
|
||
proc.terminate()
|
||
try:
|
||
proc.wait(timeout=8)
|
||
except:
|
||
proc.kill()
|
||
|
||
print(f"{anchor_name}_{title_in_name}_{now} → 启动 YouTube 推流...")
|
||
proc = subprocess.Popen(
|
||
ffmpeg_command,
|
||
stdin=subprocess.DEVNULL,
|
||
stdout=subprocess.PIPE,
|
||
stderr=subprocess.PIPE,
|
||
text=True
|
||
)
|
||
|
||
# 打印 FFmpeg 错误日志,便于排查
|
||
while True:
|
||
line = proc.stderr.readline()
|
||
if not line:
|
||
break
|
||
line = line.strip()
|
||
if line:
|
||
print(f"FFmpeg: {line}")
|
||
if proc.poll() is not None:
|
||
break
|
||
|
||
code = proc.returncode
|
||
if code != 0:
|
||
print(f"FFmpeg 退出(code={code}),5秒后重连...")
|
||
time.sleep(5)
|
||
|
||
except Exception as e:
|
||
print(f"启动 FFmpeg 异常: {e}")
|
||
time.sleep(5)
|
||
|
||
except Exception as e:
|
||
print(f"外层异常: {e}") |