m3-rec7-encoder / rec7_encode.py
PurpleOrc's picture
Upload folder using huggingface_hub
c0aa76e verified
Raw History Blame Contribute Delete
2.89 kB
#!/usr/bin/env python3
"""
rec7_encode.py — real audio -> M3 states, codes, renderer condition.
python rec7_encode.py song.mp3 --m3 /path/to/minimax_music3 --out song_rec7.pt
Writes a .pt with:
h [T, 4096] float16 the states (what the LM would have produced)
codes [T, 8] int16 c0 (16384-way) + c1..c7 (1024-way each)
cond [T, 32768] float16 optional (--cond): the renderer condition
z [128, L] float16 optional (--z): the Flow-VAE latents
25 frames per second. Works on the whole file (any length).
"""
import argparse
import sys
from pathlib import Path
import torch
HERE = Path(__file__).resolve().parent
sys.path.insert(0, str(HERE))
def main() -> int:
ap = argparse.ArgumentParser()
ap.add_argument("audio", type=Path)
ap.add_argument("--m3", type=Path, required=True,
help="MiniMax-Music3 checkpoint directory")
ap.add_argument("--weights", type=Path, default=HERE / "weights")
ap.add_argument("--out", type=Path, default=None)
ap.add_argument("--seconds", type=float, default=0,
help="0 = whole file")
ap.add_argument("--cond", action="store_true",
help="also write the 32768-d renderer condition")
ap.add_argument("--z", action="store_true", help="also write latents")
a = ap.parse_args()
import torchaudio
from rec7_model import (load_rec7, load_dav, lm_semantic_tables,
encode_audio, read_states, states_to_streams)
dev = "cuda"
wav, sr = torchaudio.load(str(a.audio))
if sr != 44100:
wav = torchaudio.transforms.Resample(sr, 44100)(wav)
if wav.shape[0] == 1:
wav = wav.repeat(2, 1)
wav = wav[:2].float()
if a.seconds > 0:
wav = wav[:, : int(a.seconds * 44100)]
dav = load_dav(a.m3, dev)
z = encode_audio(dav, wav, dev)
del dav
torch.cuda.empty_cache()
trunk, head = load_rec7(a.weights, dev)
h = read_states(trunk, head, z, dev)
del trunk, head
torch.cuda.empty_cache()
from diffusers.models.transformers.minimax_music3_rvq_depth_decoder \
import MiniMaxMusic3RVQDepthDecoder
depth = MiniMaxMusic3RVQDepthDecoder.from_pretrained(
str(a.m3 / "rvq_depth_decoder"), torch_dtype=torch.bfloat16
).to(dev).eval()
W_head, W_embed = lm_semantic_tables(a.m3, dev)
codes, cond = states_to_streams(h, depth, W_head, W_embed, dev)
out = {"h": h.cpu().to(torch.float16), "codes": codes.to(torch.int16),
"frame_rate": 25, "source": str(a.audio)}
if a.cond:
out["cond"] = cond.cpu().to(torch.float16)
if a.z:
out["z"] = z.to(torch.float16)
p = a.out or a.audio.with_suffix(".rec7.pt")
torch.save(out, p)
print(f"{p}: {h.shape[0]} frames ({h.shape[0] / 25:.1f}s)")
return 0
if __name__ == "__main__":
raise SystemExit(main())