Files
blind/audio_1/scripts/04_gen_music_acestep.py
T
xslandClaude Sonnet 4.6 e5d3d44f9d 移除 GPT-SoVITS 和 Fish Speech,整理 audio_1 脚本与文档
- 删除 03_gen_tts_gptsovits.py、00_transcribe_refs.py、ref_texts.json
- 删除 02_gen_tts_fishspeech.py 及 tts/v2_fishspeech/ 生成结果
- 保留 VoxCPM2 / ACE-Step / Stable Audio 三条链路
- 更新执行文档和技术报告,清除两款 TTS 的所有引用

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 23:12:01 +08:00

123 lines
4.5 KiB
Python

#!/usr/bin/env python3
"""
步骤 4:音乐 v1 — ACE-Step 1.5 批量生成
输出目录:audio_1/music/v1_acestep/{music,sfx,ambience}/
使用方法:
conda activate acestep
python audio_1/scripts/04_gen_music_acestep.py [--dry-run]
"""
import os, sys, time, argparse, subprocess
import torch
torch.backends.cuda.preferred_blas_library("cublaslt")
PROJECT_DIR = "/home/xsl/blind"
REPO_DIR = "/home/xsl/tools/ACE-Step-1.5"
OUT_MUSIC = f"{PROJECT_DIR}/audio_1/music/v1_acestep/music"
OUT_SFX = f"{PROJECT_DIR}/audio_1/music/v1_acestep/sfx"
OUT_AMB = f"{PROJECT_DIR}/audio_1/music/v1_acestep/ambience"
for d in (OUT_MUSIC, OUT_SFX, OUT_AMB):
os.makedirs(d, exist_ok=True)
sys.path.insert(0, REPO_DIR)
sys.path.insert(0, f"{PROJECT_DIR}/audio")
# 复用原脚本中的 TRACKS 和 SFX 定义
from gen_music_acestep import BGM_TRACKS, RINGTONES
from gen_sfx_acestep import SFX_TRACKS, AMBIENCE_TRACKS
def wav_to_mp3(src, dst):
subprocess.run(["ffmpeg", "-y", "-i", src, "-codec:a", "libmp3lame",
"-b:a", "128k", "-ar", "44100", "-ac", "2", dst],
check=True, capture_output=True)
# ──────────────────────────────────────────────────────────────
def load_handler():
from acestep.handler import AceStepHandler
print("加载 ACE-Step 模型...", end=" ", flush=True)
t0 = time.time()
handler = AceStepHandler()
handler.initialize_service(project_root=REPO_DIR, config_path="acestep-v15-turbo", device="cuda")
print(f"就绪 ({time.time()-t0:.1f}s)")
return handler
def generate_one(handler, track, out_dir):
from acestep.inference import GenerationParams, GenerationConfig, generate_music
filename = track["filename"]
out_wav = os.path.join(out_dir, f"{filename}_v1.wav")
out_mp3 = os.path.join(out_dir, f"{filename}_v1.mp3")
if os.path.exists(out_mp3):
print(f" [SKIP] {filename}")
return "skip"
note = track.get("note", "")
print(f" [{filename}] {track['duration']}s {note} ...", end=" ", flush=True)
params = GenerationParams(
caption=track["caption"],
lyrics=track.get("lyrics", ""),
duration=track["duration"],
instrumental=True,
inference_steps=track.get("steps", 20),
seed=track.get("seed", 42),
)
config = GenerationConfig(batch_size=1, audio_format="wav")
t0 = time.time()
try:
result = generate_music(handler, None, params, config, save_dir=out_dir)
elapsed = time.time() - t0
if result.success:
gen_path = result.audios[0]["path"]
if gen_path != out_wav:
os.rename(gen_path, out_wav)
wav_to_mp3(out_wav, out_mp3)
size = os.path.getsize(out_mp3) // 1024
print(f"ok {elapsed:.1f}s {size}KB")
return "ok"
else:
print(f"FAIL: {result.error}"); return "fail"
except Exception as e:
print(f"FAIL: {e}"); return "fail"
# ──────────────────────────────────────────────────────────────
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--dry-run", action="store_true")
parser.add_argument("--category", choices=["music","sfx","ambience","all"], default="all")
args = parser.parse_args()
all_tasks = []
if args.category in ("music", "all"):
all_tasks += [(t, OUT_MUSIC) for t in BGM_TRACKS + RINGTONES]
if args.category in ("sfx", "all"):
all_tasks += [(t, OUT_SFX) for t in SFX_TRACKS]
if args.category in ("ambience", "all"):
all_tasks += [(t, OUT_AMB) for t in AMBIENCE_TRACKS]
print(f"\n{'='*60}")
print(f" 音乐 v1 — ACE-Step ({len(all_tasks)} 条)")
print(f"{'='*60}\n")
if args.dry_run:
for t, d in all_tasks:
mp3 = os.path.join(d, f"{t['filename']}_v1.mp3")
done = "✓" if os.path.exists(mp3) else "·"
print(f" [{done}] {t['filename']} {t['duration']}s → {os.path.basename(d)}/")
return
handler = load_handler()
ok = fail = skip = 0
for track, out_dir in all_tasks:
r = generate_one(handler, track, out_dir)
if r == "ok": ok += 1
elif r == "skip": skip += 1
else: fail += 1
print(f"\n完成: {ok} ok, {skip} skip, {fail} fail")
if __name__ == "__main__":
main()