从github迁移过来
This commit is contained in:
@@ -0,0 +1,251 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
《林夏》BGM + 角色铃声 批量生成脚本
|
||||
使用 ACE-Step 1.5 本地模型
|
||||
|
||||
用法:
|
||||
conda activate acestep
|
||||
python audio/gen_music_acestep.py [--category bgm|ringtone|all] [--dry-run]
|
||||
"""
|
||||
import os, sys, time, argparse
|
||||
|
||||
# ── ACE-Step 修复(RTX 5090 cuBLAS)──────────────────────────
|
||||
import torch
|
||||
torch.backends.cuda.preferred_blas_library("cublaslt")
|
||||
|
||||
REPO_DIR = "/home/xsl/tools/ACE-Step-1.5"
|
||||
OUT_DIR = "/home/xsl/blind/audio/00_raw/music"
|
||||
os.makedirs(OUT_DIR, exist_ok=True)
|
||||
|
||||
sys.path.insert(0, REPO_DIR)
|
||||
|
||||
# ── BGM 四段 ─────────────────────────────────────────────────
|
||||
BGM_TRACKS = [
|
||||
{
|
||||
"filename": "lv11_bgm_m1_main_loop",
|
||||
"duration": 90,
|
||||
"caption": (
|
||||
"lo-fi midnight bedroom, soft piano, light vinyl crackle, "
|
||||
"muted piano, subtle synth pad, occasional distant rain, "
|
||||
"melancholy but warm, alone but not lonely, "
|
||||
"ambient loop, no drums, no clear melody peak, 70 bpm"
|
||||
),
|
||||
"lyrics": "",
|
||||
"steps": 20,
|
||||
"seed": 2103,
|
||||
"note": "M1 · 21:00 主题 Loop",
|
||||
},
|
||||
{
|
||||
"filename": "lv11_bgm_m2_suspense",
|
||||
"duration": 30,
|
||||
"caption": (
|
||||
"subtle ambient suspense, cinematic tension, "
|
||||
"low drone, single hanging piano note high register, sparse strings, "
|
||||
"unsettling but not horror, like a question mark, "
|
||||
"builds slowly, ends on unresolved chord, 60 bpm"
|
||||
),
|
||||
"lyrics": "",
|
||||
"steps": 20,
|
||||
"seed": 2230,
|
||||
"note": "M2 · 22:30 悬疑过门",
|
||||
},
|
||||
{
|
||||
"filename": "lv11_bgm_m3_zhounan",
|
||||
"duration": 120,
|
||||
"caption": (
|
||||
"gentle indie folk, intimate acoustic, "
|
||||
"fingerpicked nylon guitar, wordless soft humming no lyrics just mmm, "
|
||||
"light shaker, hopeful nostalgic like reading an old letter, "
|
||||
"gradual build soft climax at 80 seconds gentle outro, 75 bpm"
|
||||
),
|
||||
"lyrics": "",
|
||||
"steps": 25,
|
||||
"seed": 2345,
|
||||
"note": "M3 · 23:45 周南段落",
|
||||
},
|
||||
{
|
||||
"filename": "lv11_bgm_m4_ending",
|
||||
"duration": 90,
|
||||
"caption": (
|
||||
"warm cinematic piano, dawn moment, solo piano, "
|
||||
"soft string pad entering at 30 seconds, "
|
||||
"like the moment you realize you survived a hard night, "
|
||||
"single melody line, no drums, fade out, 50 bpm"
|
||||
),
|
||||
"lyrics": "",
|
||||
"steps": 20,
|
||||
"seed": 200,
|
||||
"note": "M4 · 02:00 结尾",
|
||||
},
|
||||
]
|
||||
|
||||
# ── 角色铃声 9 个 ──────────────────────────────────────────────
|
||||
RINGTONES = [
|
||||
{
|
||||
"filename": "lv11_ring_mom",
|
||||
"duration": 6,
|
||||
"caption": "warm marimba ringtone, simple 4-note motif, old Nokia style, 70 bpm, loop",
|
||||
"note": "妈妈铃声",
|
||||
"seed": 1001,
|
||||
},
|
||||
{
|
||||
"filename": "lv11_ring_azhe",
|
||||
"duration": 5,
|
||||
"caption": "cold minimal electronic ringtone, 2 notes only, distant, 80 bpm, loop",
|
||||
"note": "阿哲铃声",
|
||||
"seed": 1002,
|
||||
},
|
||||
{
|
||||
"filename": "lv11_ring_xiaomei",
|
||||
"duration": 5,
|
||||
"caption": "cheerful pop ringtone, ukulele plucks, 4-bar phrase, energetic, 100 bpm, loop",
|
||||
"note": "小美铃声",
|
||||
"seed": 1003,
|
||||
},
|
||||
{
|
||||
"filename": "lv11_ring_zhounan",
|
||||
"duration": 5,
|
||||
"caption": "nostalgic 90s chime, soft marimba, gentle, 70 bpm, loop",
|
||||
"note": "周南铃声",
|
||||
"seed": 1004,
|
||||
},
|
||||
{
|
||||
"filename": "lv11_ring_hr",
|
||||
"duration": 5,
|
||||
"caption": "corporate professional ringtone, neutral marimba, clean, 90 bpm, loop",
|
||||
"note": "HR王姐铃声",
|
||||
"seed": 1005,
|
||||
},
|
||||
{
|
||||
"filename": "lv11_ring_anan",
|
||||
"duration": 4,
|
||||
"caption": "bouncy J-pop intro ringtone, bright, energetic, 110 bpm, loop",
|
||||
"note": "安安铃声",
|
||||
"seed": 1006,
|
||||
},
|
||||
{
|
||||
"filename": "lv11_ring_dorm_group",
|
||||
"duration": 5,
|
||||
"caption": "soft group notification chime, friendly, warm bells, 80 bpm, loop",
|
||||
"note": "寝室群铃声",
|
||||
"seed": 1007,
|
||||
},
|
||||
{
|
||||
"filename": "lv11_ring_unknown",
|
||||
"duration": 6,
|
||||
"caption": "eerie low drone ringtone, no melody, unsettling, 40 bpm, dark ambient, loop",
|
||||
"note": "未知号码铃声",
|
||||
"seed": 1008,
|
||||
},
|
||||
{
|
||||
"filename": "lv11_ring_delivery",
|
||||
"duration": 3,
|
||||
"caption": "short delivery notification beep, simple two-tone, neutral, 90 bpm",
|
||||
"note": "外卖铃声",
|
||||
"seed": 1009,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def load_handler():
|
||||
"""初始化 ACE-Step handler(带 cublaslt 修复)"""
|
||||
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) dtype={handler.dtype}")
|
||||
return handler
|
||||
|
||||
|
||||
def generate_one(handler, track, is_ringtone=False):
|
||||
"""生成单条音频,返回输出路径或 None"""
|
||||
from acestep.inference import GenerationParams, GenerationConfig, generate_music
|
||||
|
||||
filename = track["filename"]
|
||||
out_path = os.path.join(OUT_DIR, f"{filename}_v1.wav")
|
||||
|
||||
if os.path.exists(out_path):
|
||||
print(f" [跳过] {filename}(已存在)")
|
||||
return out_path
|
||||
|
||||
note = track.get("note", "")
|
||||
print(f" 生成: {filename} [{note}] {track['duration']}s ...", 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),
|
||||
)
|
||||
from acestep.inference import GenerationConfig
|
||||
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_path:
|
||||
os.rename(gen_path, out_path)
|
||||
print(f"✓ {elapsed:.1f}s → {os.path.basename(out_path)}")
|
||||
return out_path
|
||||
else:
|
||||
print(f"✗ {result.error}")
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f"✗ {e}")
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--category", choices=["bgm", "ringtone", "all"], default="all")
|
||||
parser.add_argument("--dry-run", action="store_true")
|
||||
args = parser.parse_args()
|
||||
|
||||
all_tracks = []
|
||||
if args.category in ("bgm", "all"):
|
||||
all_tracks += [("bgm", t) for t in BGM_TRACKS]
|
||||
if args.category in ("ringtone", "all"):
|
||||
all_tracks += [("ringtone", t) for t in RINGTONES]
|
||||
|
||||
print(f"\n{'='*60}")
|
||||
print(f"《林夏》音乐生成 共 {len(all_tracks)} 条")
|
||||
print(f"输出目录: {OUT_DIR}")
|
||||
print(f"{'='*60}")
|
||||
|
||||
if args.dry_run:
|
||||
for cat, t in all_tracks:
|
||||
exists = "✓" if os.path.exists(os.path.join(OUT_DIR, f"{t['filename']}_v1.wav")) else "○"
|
||||
print(f" [{exists}][{cat}] {t['filename']} {t['duration']}s {t.get('note','')}")
|
||||
return
|
||||
|
||||
handler = load_handler()
|
||||
|
||||
ok, skip, fail = 0, 0, 0
|
||||
for cat, track in all_tracks:
|
||||
result = generate_one(handler, track, is_ringtone=(cat == "ringtone"))
|
||||
if result is None:
|
||||
fail += 1
|
||||
elif "跳过" in str(result):
|
||||
skip += 1
|
||||
else:
|
||||
ok += 1
|
||||
|
||||
print(f"\n{'='*60}")
|
||||
print(f"完成 {ok} 跳过 {skip} 失败 {fail}")
|
||||
print(f"输出: {OUT_DIR}")
|
||||
print(f"{'='*60}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user