Abdelrahman2922's picture
Add files using upload-large-folder tool
8d6afae verified
Raw
History Blame Contribute Delete
4.77 kB
"""Single-item inference CLI for OmniVoice.
Generates audio from a single text input using voice cloning,
voice design, or auto voice.
Usage:
# Voice cloning
omnivoice-infer --model k2-fsa/OmniVoice \
--text "Hello, this is a text for text-to-speech." \
--ref_audio ref.wav --ref_text "Reference transcript." --output out.wav
# Voice design
omnivoice-infer --model k2-fsa/OmniVoice \
--text "Hello, this is a text for text-to-speech." \
--instruct "male, British accent" --output out.wav
# Auto voice
omnivoice-infer --model k2-fsa/OmniVoice \
--text "Hello, this is a text for text-to-speech." --output out.wav
"""
import argparse
import logging
import torch
import soundfile as sf
from omnivoice.models.omnivoice import OmniVoice
from omnivoice.utils.common import str2bool
def get_best_device():
"""Auto-detect the best available device: CUDA > MPS > CPU."""
if torch.cuda.is_available():
return "cuda"
if torch.backends.mps.is_available():
return "mps"
return "cpu"
def get_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
description="OmniVoice single-item inference",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
parser.add_argument(
"--model",
type=str,
default="k2-fsa/OmniVoice",
help="Model checkpoint path or HuggingFace repo id.",
)
parser.add_argument(
"--text",
type=str,
required=True,
help="Text to synthesize.",
)
parser.add_argument(
"--output",
type=str,
required=True,
help="Output WAV file path.",
)
# Voice cloning
parser.add_argument(
"--ref_audio",
type=str,
default=None,
help="Reference audio file path for voice cloning.",
)
parser.add_argument(
"--ref_text",
type=str,
default=None,
help="Reference text describing the reference audio.",
)
# Voice design
parser.add_argument(
"--instruct",
type=str,
default=None,
help="Style instruction for voice design mode.",
)
parser.add_argument(
"--language",
type=str,
default=None,
help="Language name (e.g. 'English') or code (e.g. 'en').",
)
# Generation parameters
parser.add_argument("--num_step", type=int, default=32)
parser.add_argument("--guidance_scale", type=float, default=2.0)
parser.add_argument("--speed", type=float, default=1.0)
parser.add_argument(
"--duration",
type=float,
default=None,
help="Fixed output duration in seconds. If set, overrides the "
"model's duration estimation. The speed factor is automatically "
"adjusted to match while preserving language-aware pacing.",
)
parser.add_argument("--t_shift", type=float, default=0.1)
parser.add_argument("--denoise", type=str2bool, default=True)
parser.add_argument(
"--postprocess_output",
type=str2bool,
default=True,
)
parser.add_argument("--layer_penalty_factor", type=float, default=5.0)
parser.add_argument("--position_temperature", type=float, default=5.0)
parser.add_argument("--class_temperature", type=float, default=0.0)
parser.add_argument(
"--device",
type=str,
default=None,
help="Device to use for inference. Auto-detected if not specified.",
)
return parser
def main():
formatter = "%(asctime)s %(levelname)s [%(filename)s:%(lineno)d] %(message)s"
logging.basicConfig(format=formatter, level=logging.INFO, force=True)
args = get_parser().parse_args()
device = args.device or get_best_device()
logging.info(f"Loading model from {args.model} on {device} ...")
model = OmniVoice.from_pretrained(
args.model, device_map=device, dtype=torch.float16
)
logging.info(f"Generating audio for: {args.text[:80]}...")
audios = model.generate(
text=args.text,
language=args.language,
ref_audio=args.ref_audio,
ref_text=args.ref_text,
instruct=args.instruct,
duration=args.duration,
num_step=args.num_step,
guidance_scale=args.guidance_scale,
speed=args.speed,
t_shift=args.t_shift,
denoise=args.denoise,
postprocess_output=args.postprocess_output,
layer_penalty_factor=args.layer_penalty_factor,
position_temperature=args.position_temperature,
class_temperature=args.class_temperature,
)
sf.write(args.output, audios[0], model.sampling_rate)
logging.info(f"Saved to {args.output}")
if __name__ == "__main__":
main()