From def681cbe39551453f68404785a07d1d77385017 Mon Sep 17 00:00:00 2001 From: eric Date: Thu, 19 Mar 2026 03:24:58 -0500 Subject: [PATCH] 's' --- config/youtube.ini | 1 + demucs_pipeline.py | 25 +++++++++++++++++-------- douyin_youtube_ffplay.py | 2 +- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/config/youtube.ini b/config/youtube.ini index edee910..4eb8ca9 100644 --- a/config/youtube.ini +++ b/config/youtube.ini @@ -11,6 +11,7 @@ stats_interval_sec = 10 # ===== 其次:音频版权处理 ===== # 是否启用 Demucs 人声分离(防 YouTube Content ID 版权识别) +# 若推流几十秒后断流(YouTube 显示 no data),可设为 否 使用原始音频 # 是 = 启用,只保留人声;否 = 使用原始音频 enable_demucs = 是 diff --git a/demucs_pipeline.py b/demucs_pipeline.py index c828214..4e849f6 100644 --- a/demucs_pipeline.py +++ b/demucs_pipeline.py @@ -69,8 +69,8 @@ def _load_demucs_model(use_gpu: bool): # Demucs 模型采样率 DEMUCS_SAMPLE_RATE = 44100 DEMUCS_CHANNELS = 2 -# 每次处理的音频长度(秒),影响延迟与质量 -DEMUCS_CHUNK_SEC = 2.0 +# 每次处理的音频长度(秒),1.0 更易实时,2.0 质量更好但 P40 可能跟不上 +DEMUCS_CHUNK_SEC = 1.0 # 字节 per sample (s16le: 2 bytes) BYTES_PER_SAMPLE = 2 @@ -92,7 +92,7 @@ def _demucs_separate_vocals(model, audio_chunk, device, vocal_mix_ratio=1.0, mix if wav.dim() == 2: wav = wav.unsqueeze(0) with torch.no_grad(): - out = apply_model(model, wav, device=device, progress=False, overlap=0.25) + out = apply_model(model, wav, device=device, progress=False, overlap=0.1) # out: (batch, sources, channels, samples) # sources: [drums=0, bass=1, other=2, vocals=3] vocals = out[0, 3] @@ -269,19 +269,27 @@ def run_demucs_pipeline( "-b:v", f"{nvenc_params.get('video_bitrate_k', 4500)}k", "-maxrate", f"{nvenc_params.get('video_bitrate_k', 4500)+500}k", "-bufsize", f"{nvenc_params.get('video_bitrate_k', 4500)*2}k", - "-vsync", "cfr", "-g", "60", "-keyint_min", "60", "-r", "30", - "-bf", "0", "-sc_threshold", "0", - "-x264-params", "force-cfr=1:scenecut=0:open_gop=0:sync-lookahead=0", + "-fps_mode", "cfr", "-g", "60", "-keyint_min", "60", "-r", "30", + "-bf", "0", "-pix_fmt", "yuv420p", "-c:a", "aac", "-b:a", "128k", "-ar", "48000", "-ac", "2", "-af", "lowpass=f=9000,aresample=async=1:first_pts=0", "-flags", "+global_header", "-flvflags", "no_duration_filesize", "-f", "flv", youtube_rtmp, ] - if nvenc_params.get("tune_param"): + # NVENC 用 tune_param;libx264 用 sc_threshold + x264-params + codec = nvenc_params.get("codec_v", "libx264") + if nvenc_params.get("tune_param") and codec == "h264_nvenc": idx = ffmpeg_out_cmd.index("-profile:v") for p in reversed(nvenc_params["tune_param"]): ffmpeg_out_cmd.insert(idx, p) + elif codec == "libx264": + idx = ffmpeg_out_cmd.index("-bf") + ffmpeg_out_cmd.insert(idx + 2, "-sc_threshold") + ffmpeg_out_cmd.insert(idx + 3, "0") + idx = ffmpeg_out_cmd.index("-pix_fmt") + ffmpeg_out_cmd.insert(idx, "-x264-params") + ffmpeg_out_cmd.insert(idx + 1, "force-cfr=1:scenecut=0:open_gop=0:sync-lookahead=0") proc_v = None proc_a = None @@ -385,7 +393,8 @@ def run_demucs_pipeline( except queue.Empty: # 若 proc_out(推流进程)已异常退出,立即报告 if proc_out.poll() is not None and proc_out.returncode != 0: - print(f"[ERROR] YouTube 推流进程已退出,返回码: {proc_out.returncode}") + print(f"[ERROR] YouTube 推流进程已退出,返回码: {proc_out.returncode},可能是 Demucs 处理跟不上或网络问题") + print(f"[TIP] 若频繁断流,可尝试 config/youtube.ini 中设置 enable_demucs = 否 使用原始音频") break if time.time() - getattr(proc_v, "last_out_ts", time.time()) > stale_output_seconds: print("[WARN] 长时间无任何日志,强制重启进程") diff --git a/douyin_youtube_ffplay.py b/douyin_youtube_ffplay.py index 0ba6e54..105b002 100644 --- a/douyin_youtube_ffplay.py +++ b/douyin_youtube_ffplay.py @@ -258,7 +258,7 @@ def start_douyin_youtube_ffplay( "-profile:v", "high", # 720p,画质优先,YouTube 推荐 3-8 Mbps "-b:v", f"{br_k}k", "-maxrate", f"{br_k+500}k", "-bufsize", f"{br_k*2}k", - "-vsync", "cfr", + "-fps_mode", "cfr", "-g", "60", "-keyint_min", "60", "-r", "30", "-bf", "0",