Spaces:
Runtime error
Runtime error
File size: 6,386 Bytes
1d37a77 e60eef2 1d37a77 e60eef2 1d37a77 16c1169 720d9d0 e60eef2 1d37a77 e60eef2 1d37a77 e60eef2 1d37a77 e60eef2 720d9d0 e60eef2 16c1169 e60eef2 1d37a77 e60eef2 1d37a77 720d9d0 1d37a77 587ef66 16c1169 1d37a77 e60eef2 16c1169 1d37a77 e60eef2 1d37a77 e60eef2 1d37a77 e60eef2 1d37a77 e60eef2 1d37a77 e60eef2 1d37a77 e60eef2 1d37a77 e60eef2 1d37a77 e60eef2 1d37a77 e60eef2 1d37a77 e60eef2 1d37a77 e60eef2 1d37a77 e60eef2 1d37a77 e60eef2 1d37a77 e60eef2 1d37a77 e60eef2 1d37a77 e60eef2 1d37a77 4b91de4 e60eef2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | import os, sys, torch, gradio as gr, tempfile, uuid, re, numpy as np, gc
import torchaudio
from torchaudio.transforms import Resample
from omegaconf import OmegaConf
from tqdm import tqdm
from einops import rearrange
from transformers import (
AutoTokenizer, AutoModelForCausalLM,
LogitsProcessor, LogitsProcessorList
)
from huggingface_hub import snapshot_download, login
# ----------------- Hugging Face Authentication -----------------
HF_TOKEN = os.getenv("HF_TOKEN") # β
Read securely from environment variable
if HF_TOKEN:
login(token=HF_TOKEN)
print("π Logged into Hugging Face successfully.")
else:
print("β οΈ No Hugging Face token found. Please set it in your environment variables.")
# ----------------- Basic Environment Setup -----------------
print("π§ Initializing environment (CPU mode)...")
os.environ["PYTORCH_JIT"] = "0"
torch.set_num_threads(1)
torch.backends.cuda.matmul.allow_tf32 = False
torch.backends.cudnn.benchmark = False
device = "cpu"
# ----------------- Model Download -----------------
folder_path = './xcodec_mini_infer'
os.makedirs(folder_path, exist_ok=True)
print(f"π¦ Folder ready: {folder_path}")
snapshot_download(
repo_id="m-a-p/xcodec_mini_infer",
local_dir="./xcodec_mini_infer",
token=HF_TOKEN
)
sys.path.append(os.path.join(os.path.dirname(__file__), 'xcodec_mini_infer'))
sys.path.append(os.path.join(os.path.dirname(__file__), 'xcodec_mini_infer', 'descriptaudiocodec'))
from codecmanipulator import CodecManipulator
from mmtokenizer import _MMSentencePieceTokenizer
from models.soundstream_hubert_new import SoundStream
# ----------------- Load YuE Model -----------------
print("π§ Loading YuE model on CPU (small version)...")
try:
model = AutoModelForCausalLM.from_pretrained(
"m-a-p/YuE-upsampler",
torch_dtype=torch.float32,
attn_implementation="eager",
low_cpu_mem_usage=True,
device_map={"": "cpu"},
token=HF_TOKEN
)
model.eval()
print("β
YuE model loaded successfully.")
except Exception as e:
print(f"β Model loading failed: {e}")
sys.exit(1)
# ----------------- Load Codec -----------------
print("π§ Loading codec model...")
basic_model_config = './xcodec_mini_infer/final_ckpt/config.yaml'
resume_path = './xcodec_mini_infer/final_ckpt/ckpt_00100000.pth'
mmtokenizer = _MMSentencePieceTokenizer("./mm_tokenizer_v0.2_hf/tokenizer.model")
codectool = CodecManipulator("xcodec", 0, 1)
model_config = OmegaConf.load(basic_model_config)
codec_model = eval(model_config.generator.name)(**model_config.generator.config).to(device)
state_dict = torch.load(resume_path, map_location="cpu")
codec_model.load_state_dict(state_dict['codec_model'])
codec_model.eval()
print("β
Codec model loaded successfully.")
# ---------------- Utility -----------------
class BlockTokenRangeProcessor(LogitsProcessor):
def __init__(self, start_id, end_id):
self.blocked_token_ids = list(range(start_id, end_id))
def __call__(self, input_ids, scores):
scores[:, self.blocked_token_ids] = -float("inf")
return scores
def split_lyrics(lyrics: str):
pattern = r"\[(\w+)\]\s*(.*?)(?=\s*\n\[|\Z)"
segments = re.findall(pattern, lyrics, re.DOTALL)
return [f"[{seg[0]}]\n{seg[1].strip()}\n\n" for seg in segments]
def save_audio(wav: torch.Tensor, path, sample_rate: int, rescale: bool = False):
limit = 0.99
max_val = wav.abs().max()
wav = wav * min(limit / max_val, 1) if rescale else wav.clamp(-limit, limit)
torchaudio.save(str(path), wav, sample_rate=sample_rate, encoding='PCM_S', bits_per_sample=16)
# ---------------- Generation -----------------
def generate_music(genre_txt, lyrics_txt, progress=gr.Progress()):
with tempfile.TemporaryDirectory() as output_dir:
genres = genre_txt.strip()
lyrics = split_lyrics(lyrics_txt + "\n")
prompt_texts = [f"Generate music from lyrics.\n[Genre] {genres}\n" + "\n".join(lyrics)]
random_id = uuid.uuid4()
print("πΆ Generating music...")
start_of_segment = mmtokenizer.tokenize('[start_of_segment]')
end_of_segment = mmtokenizer.tokenize('[end_of_segment]')
head_id = mmtokenizer.tokenize(prompt_texts[0])
prompt_ids = torch.as_tensor(head_id + start_of_segment + [mmtokenizer.soa]).unsqueeze(0).to(device)
with torch.inference_mode():
output_seq = model.generate(
input_ids=prompt_ids,
max_new_tokens=32,
top_p=0.9,
temperature=0.8,
repetition_penalty=1.1,
eos_token_id=mmtokenizer.eoa,
pad_token_id=mmtokenizer.eoa,
logits_processor=LogitsProcessorList([BlockTokenRangeProcessor(0, 32002)]),
)
ids = output_seq[0].cpu().numpy()
soa_idx = np.where(ids == mmtokenizer.soa)[0].tolist()
eoa_idx = np.where(ids == mmtokenizer.eoa)[0].tolist()
vocals, instr = [], []
for i in range(len(soa_idx)):
codec_ids = ids[soa_idx[i] + 1:eoa_idx[i]]
codec_ids = codec_ids[:2 * (len(codec_ids) // 2)]
v = codectool.ids2npy(rearrange(codec_ids, "(n b) -> b n", b=2)[0])
vocals.append(v)
ins = codectool.ids2npy(rearrange(codec_ids, "(n b) -> b n", b=2)[1])
instr.append(ins)
vocals = np.concatenate(vocals, axis=1)
instr = np.concatenate(instr, axis=1)
mix = (vocals + instr) / 2
recons_dir = os.path.join(output_dir, "recons")
os.makedirs(recons_dir, exist_ok=True)
mix_path = os.path.join(recons_dir, f"mix_{random_id}.wav")
save_audio(torch.tensor(mix).unsqueeze(0), mix_path, 16000)
gc.collect()
print("β
Generation complete.")
return mix_path
# ---------------- Gradio Interface -----------------
with gr.Blocks() as demo:
gr.Markdown("# π΅ YuE CPU Music Generator (Low-Memory Edition)")
genre_txt = gr.Textbox(label="Genre", placeholder="Pop, Jazz, Hip-Hop...")
lyrics_txt = gr.Textbox(label="Lyrics", placeholder="[Verse]\nI walk the night...")
music_out = gr.Audio(label="Generated Song")
btn = gr.Button("Generate πΆ")
btn.click(generate_music, inputs=[genre_txt, lyrics_txt], outputs=[music_out])
demo.queue().launch(show_error=True, share=True)
|