From 77969c85fe03b78afa0d39e74e1af1efba35a1a9 Mon Sep 17 00:00:00 2001 From: eric Date: Thu, 19 Mar 2026 13:46:02 -0500 Subject: [PATCH] 's' --- config/URL_config.ini | 1 + config/youtube.ini | 3 +- docs/REALTIME_AUDIO_DEMUCS.md | 119 ++++++++++++++++++++++++++++++++++ douyin_youtube_ffplay.py | 14 ++-- 4 files changed, 132 insertions(+), 5 deletions(-) create mode 100644 docs/REALTIME_AUDIO_DEMUCS.md diff --git a/config/URL_config.ini b/config/URL_config.ini index 8e23ce3..6b81c76 100644 --- a/config/URL_config.ini +++ b/config/URL_config.ini @@ -7,3 +7,4 @@ https://live.douyin.com/562629369787,主播: 叹茶柠檬茶 https://live.douyin.com/565208465584,主播: 财圆圆 https://live.douyin.com/51142028798,主播: 小夏妹妹 https://live.douyin.com/974451428277,主播: 雅如柠檬茶 +https://live.douyin.com/334176667239,主播: 樱桃炒饭(摆摊版) diff --git a/config/youtube.ini b/config/youtube.ini index f5dc080..c3e43c6 100644 --- a/config/youtube.ini +++ b/config/youtube.ini @@ -1,6 +1,7 @@ [youtube] # 必填:YouTube 直播推流 key(在 YouTube 工作室 → 创建 → 流式传输 获取) -key = x04z-564w-aks7-embw-30y4 +key = qxvb-r47b-r5ju-6ud3-6k7z +; key = x04z-564w-aks7-embw-30y4 # 可选:是否使用 RTMPS 加密推流,填 否 则用 RTMP(默认 RTMPS) ; rtmps = 否 diff --git a/docs/REALTIME_AUDIO_DEMUCS.md b/docs/REALTIME_AUDIO_DEMUCS.md new file mode 100644 index 0000000..8f7b5b4 --- /dev/null +++ b/docs/REALTIME_AUDIO_DEMUCS.md @@ -0,0 +1,119 @@ +# 实时音频处理最佳方案(Demucs + RTX 3060) + +## 一、方案对比 + +| 方案 | 版权规避率 | 延迟 | 算力 | 复杂度 | +|------|------------|------|------|--------| +| **FFmpeg 纯滤波**(当前) | 60-70% | 0 | 低 | 低 | +| **Demucs 人声分离** | 90%+ | 4-8s | RTX 3060 | 中高 | + +--- + +## 二、推荐架构:Demucs 实时管道 + +``` +抖音流 ─┬─ FFmpeg 解复用 ─┬─ 视频 ─────────────────────────────┐ + │ │ │ + │ └─ 音频 ─→ Python Demucs ─→ 人声 ────┼─→ FFmpeg 复用 ─→ YouTube RTMP + │ (分块处理) │ + └────────────────────────────────────────────────────┘ +``` + +### 核心参数(RTX 3060 12GB) + +| 参数 | 推荐值 | 说明 | +|------|--------|------| +| **模型** | `htdemucs`(单模型,非 _ft) | 速度最快,质量够用 | +| **chunk 长度** | 2.5-3 秒 | 延迟 ≈ 2×chunk ≈ 5-6s | +| **overlap** | 0.25 | 减少接缝,质量更好 | +| **shifts** | 0 | 降低算力,实时必需 | +| **segment** | 7.8(默认)或更小 | 显存不足时减小 | + +### RTX 3060 算力 + +- 约 13 TFLOPS,高于 Demucs 实时所需 2 TFLOPS +- 12GB 显存足够 htdemucs(约 6-8GB) +- 预期:**2-4× 实时速度**,可满足直播 + +--- + +## 三、实现方式 + +### 方式 A:Python 自建管道(推荐) + +```python +# 伪代码流程 +# 1. FFmpeg 从抖音拉流,输出: -vn -acodec pcm_s16le -ar 44100 -ac 1 pipe:1 +# 2. 主进程读取音频块(2.5s = 110250 samples @ 44.1kHz) +# 3. 调用 demucs.separate_audio(model, chunk) 得到 vocals +# 4. 人声写入 pipe,FFmpeg 另一进程读取并与视频复用推流 +``` + +**依赖**: +``` +demucs +torch +torchaudio +``` + +**模型加载**: +```python +from demucs.pretrained import get_model +model = get_model('htdemucs') # 单模型,非 htdemucs_ft +``` + +### 方式 B:GStreamer(若可用) + +GStreamer 1.28+ 内置 demucs 元素,CPU 约 8× 实时: + +```bash +# 需安装 gst-plugins-rs (含 demucs) +gst-launch-1.0 uridecodebin uri=抖音流 ! audioconvert ! demucs ! ... +``` + +--- + +## 四、分块处理要点 + +1. **重叠**:chunk 之间 25% 重叠,避免接缝 +2. **队列**:双缓冲,一块处理时另一块接收 +3. **采样率**:Demucs 默认 44100 Hz,与 FFmpeg 输出一致 +4. **延迟**:总延迟 ≈ 2 × chunk 长度(约 5-6 秒可接受) + +--- + +## 五、快速验证(离线测试) + +```bash +# 安装 +pip install demucs torch torchaudio + +# 测试 30 秒音频分离速度 +demucs -n htdemucs --two-stems=vocals -j 1 test_30s.mp3 -o output/ + +# 若 30s 在 10s 内完成 → 可实时 +``` + +--- + +## 六、与当前方案的关系 + +- **当前**:`douyin_youtube_ffplay.py` 纯 FFmpeg,60-70% 规避率 +- **升级**:可新增 `douyin_youtube_demucs.py`,集成 Demucs 管道 +- **切换**:通过 config 选择 `mode = ffmpeg` 或 `mode = demucs` + +--- + +## 七、配置建议(config/youtube.ini) + +```ini +[youtube] +key = xxx + +# 音频模式: ffmpeg | demucs +; audio_mode = ffmpeg + +# Demucs 专用 +; demucs_chunk = 2.5 +; demucs_model = htdemucs +``` diff --git a/douyin_youtube_ffplay.py b/douyin_youtube_ffplay.py index e497906..24ac200 100644 --- a/douyin_youtube_ffplay.py +++ b/douyin_youtube_ffplay.py @@ -184,9 +184,13 @@ def start_douyin_youtube_ffplay( if os.path.isfile(_p): _arnndn_model = os.path.normpath(_p) break + _ffmpeg_cwd = None if _arnndn_model: print(f"[INFO] 使用 RNNoise 降噪模型: {_arnndn_model}") - _af_denoise = f"arnndn=m={_arnndn_model}:mix=0.82," + # 跨平台:用相对路径避免 Windows 下 C: 冒号破坏 FFmpeg 滤镜解析;FFmpeg 以模型所在父目录为 cwd + _arnndn_base = os.path.dirname(os.path.dirname(os.path.abspath(_arnndn_model))) + _af_denoise = "arnndn=m=arnndn-models/cb.rnnn:mix=0.82," + _ffmpeg_cwd = _arnndn_base else: print("[INFO] 未找到 arnndn 模型,使用 afftdn 降噪(可克隆 richardpl/arnndn-models 到 arnndn-models/)") _af_denoise = "afftdn=nf=-26:tn=1," @@ -254,15 +258,17 @@ def start_douyin_youtube_ffplay( stderr_q = queue.Queue() print(f"[INFO][{datetime.datetime.now():%H:%M:%S}] 启动 YouTube 推流 → {stream_title}") - proc = subprocess.Popen( - ffmpeg_command, + _popen_kw = dict( stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, text=True, bufsize=1, - universal_newlines=True + universal_newlines=True, ) + if _ffmpeg_cwd: + _popen_kw["cwd"] = _ffmpeg_cwd + proc = subprocess.Popen(ffmpeg_command, **_popen_kw) proc.last_out_ts = time.time() reader_t = threading.Thread(target=_stderr_reader_thread, args=(proc, stderr_q))