CoolFace
Apppublic

codemo/fish-speech-1

sourceHugging Facecc-by-nc-sa-4.0updated 2y agoView on Hugging Face
0likes
inference.py123 linesDownload Raw Back to vqgan
1from pathlib import Path2 3import click4import hydra5import numpy as np6import soundfile as sf7import torch8import torchaudio9from hydra import compose, initialize10from hydra.utils import instantiate11from loguru import logger12from omegaconf import OmegaConf13 14from tools.file import AUDIO_EXTENSIONS15 16# register eval resolver17OmegaConf.register_new_resolver("eval", eval)18 19 20def load_model(config_name, checkpoint_path, device="cuda"):21    hydra.core.global_hydra.GlobalHydra.instance().clear()22    with initialize(version_base="1.3", config_path="../../fish_speech/configs"):23        cfg = compose(config_name=config_name)24 25    model = instantiate(cfg)26    state_dict = torch.load(27        checkpoint_path,28        map_location=device,29    )30    if "state_dict" in state_dict:31        state_dict = state_dict["state_dict"]32 33    if any("generator" in k for k in state_dict):34        state_dict = {35            k.replace("generator.", ""): v36            for k, v in state_dict.items()37            if "generator." in k38        }39 40    result = model.load_state_dict(state_dict, strict=False)41    model.eval()42    model.to(device)43 44    logger.info(f"Loaded model: {result}")45    return model46 47 48@torch.no_grad()49@click.command()50@click.option(51    "--input-path",52    "-i",53    default="test.wav",54    type=click.Path(exists=True, path_type=Path),55)56@click.option(57    "--output-path", "-o", default="fake.wav", type=click.Path(path_type=Path)58)59@click.option("--config-name", default="firefly_gan_vq")60@click.option(61    "--checkpoint-path",62    default="checkpoints/fish-speech-1.4/firefly-gan-vq-fsq-8x1024-21hz-generator.pth",63)64@click.option(65    "--device",66    "-d",67    default="cuda",68)69def main(input_path, output_path, config_name, checkpoint_path, device):70    model = load_model(config_name, checkpoint_path, device=device)71 72    if input_path.suffix in AUDIO_EXTENSIONS:73        logger.info(f"Processing in-place reconstruction of {input_path}")74 75        # Load audio76        audio, sr = torchaudio.load(str(input_path))77        if audio.shape[0] > 1:78            audio = audio.mean(0, keepdim=True)79        audio = torchaudio.functional.resample(80            audio, sr, model.spec_transform.sample_rate81        )82 83        audios = audio[None].to(device)84        logger.info(85            f"Loaded audio with {audios.shape[2] / model.spec_transform.sample_rate:.2f} seconds"86        )87 88        # VQ Encoder89        audio_lengths = torch.tensor([audios.shape[2]], device=device, dtype=torch.long)90        indices = model.encode(audios, audio_lengths)[0][0]91 92        logger.info(f"Generated indices of shape {indices.shape}")93 94        # Save indices95        np.save(output_path.with_suffix(".npy"), indices.cpu().numpy())96    elif input_path.suffix == ".npy":97        logger.info(f"Processing precomputed indices from {input_path}")98        indices = np.load(input_path)99        indices = torch.from_numpy(indices).to(device).long()100        assert indices.ndim == 2, f"Expected 2D indices, got {indices.ndim}"101    else:102        raise ValueError(f"Unknown input type: {input_path}")103 104    # Restore105    feature_lengths = torch.tensor([indices.shape[1]], device=device)106    fake_audios, _ = model.decode(107        indices=indices[None], feature_lengths=feature_lengths108    )109    audio_time = fake_audios.shape[-1] / model.spec_transform.sample_rate110 111    logger.info(112        f"Generated audio of shape {fake_audios.shape}, equivalent to {audio_time:.2f} seconds from {indices.shape[1]} features, features/second: {indices.shape[1] / audio_time:.2f}"113    )114 115    # Save audio116    fake_audio = fake_audios[0, 0].float().cpu().numpy()117    sf.write(output_path, fake_audio, model.spec_transform.sample_rate)118    logger.info(f"Saved audio to {output_path}")119 120 121if __name__ == "__main__":122    main()123