Instructions to use autotools/ai_video_studio with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use autotools/ai_video_studio with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf autotools/ai_video_studio:Q4_K_M # Run inference directly in the terminal: llama cli -hf autotools/ai_video_studio:Q4_K_M
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf autotools/ai_video_studio:Q4_K_M # Run inference directly in the terminal: llama cli -hf autotools/ai_video_studio:Q4_K_M
Use pre-built binary
# Download pre-built binary from: # https://github.com/ggerganov/llama.cpp/releases # Start a local OpenAI-compatible server with a web UI: ./llama-server -hf autotools/ai_video_studio:Q4_K_M # Run inference directly in the terminal: ./llama-cli -hf autotools/ai_video_studio:Q4_K_M
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-server llama-cli # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama-server -hf autotools/ai_video_studio:Q4_K_M # Run inference directly in the terminal: ./build/bin/llama-cli -hf autotools/ai_video_studio:Q4_K_M
Use Docker
docker model run hf.co/autotools/ai_video_studio:Q4_K_M
- LM Studio
- Jan
- Ollama
How to use autotools/ai_video_studio with Ollama:
ollama run hf.co/autotools/ai_video_studio:Q4_K_M
- Unsloth Studio
How to use autotools/ai_video_studio with Unsloth Studio:
Install Unsloth Studio (macOS, Linux, WSL)
curl -fsSL https://unsloth.ai/install.sh | sh # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for autotools/ai_video_studio to start chatting
Install Unsloth Studio (Windows)
irm https://unsloth.ai/install.ps1 | iex # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for autotools/ai_video_studio to start chatting
Using HuggingFace Spaces for Unsloth
# No setup required # Open https://huggingface.co/spaces/unsloth/studio in your browser # Search for autotools/ai_video_studio to start chatting
- Atomic Chat new
- Docker Model Runner
How to use autotools/ai_video_studio with Docker Model Runner:
docker model run hf.co/autotools/ai_video_studio:Q4_K_M
- Lemonade
How to use autotools/ai_video_studio with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull autotools/ai_video_studio:Q4_K_M
Run and chat with the model
lemonade run user.ai_video_studio-Q4_K_M
List all available models
lemonade list
| #!/usr/bin/env python3 | |
| # Copyright 2026 Xiaomi Corp. (authors: Han Zhu) | |
| # | |
| # See ../../LICENSE for clarification regarding multiple authors | |
| # | |
| # Licensed under the Apache License, Version 2.0 (the "License"); | |
| # you may not use this file except in compliance with the License. | |
| # You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, software | |
| # distributed under the License is distributed on an "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| # See the License for the specific language governing permissions and | |
| # limitations under the License. | |
| """ | |
| Gradio demo for OmniVoice. | |
| Supports voice cloning and voice design. | |
| Usage: | |
| omnivoice-demo --model /path/to/checkpoint --port 8000 | |
| """ | |
| import argparse | |
| import logging | |
| from typing import Any, Dict | |
| import gradio as gr | |
| import numpy as np | |
| import torch | |
| from omnivoice import OmniVoice, OmniVoiceGenerationConfig | |
| from omnivoice.utils.common import get_best_device | |
| from omnivoice.utils.lang_map import LANG_NAMES, lang_display_name | |
| # --------------------------------------------------------------------------- | |
| # Language list — all 600+ supported languages | |
| # --------------------------------------------------------------------------- | |
| _ALL_LANGUAGES = ["Auto"] + sorted(lang_display_name(n) for n in LANG_NAMES) | |
| # --------------------------------------------------------------------------- | |
| # Voice Design instruction templates | |
| # --------------------------------------------------------------------------- | |
| # Each option is displayed as "English / 中文". | |
| # The model expects English for accents and Chinese for dialects. | |
| _CATEGORIES = { | |
| "Gender / 性别": ["Male / 男", "Female / 女"], | |
| "Age / 年龄": [ | |
| "Child / 儿童", | |
| "Teenager / 少年", | |
| "Young Adult / 青年", | |
| "Middle-aged / 中年", | |
| "Elderly / 老年", | |
| ], | |
| "Pitch / 音调": [ | |
| "Very Low Pitch / 极低音调", | |
| "Low Pitch / 低音调", | |
| "Moderate Pitch / 中音调", | |
| "High Pitch / 高音调", | |
| "Very High Pitch / 极高音调", | |
| ], | |
| "Style / 风格": ["Whisper / 耳语"], | |
| "English Accent / 英文口音": [ | |
| "American Accent / 美式口音", | |
| "Australian Accent / 澳大利亚口音", | |
| "British Accent / 英国口音", | |
| "Chinese Accent / 中国口音", | |
| "Canadian Accent / 加拿大口音", | |
| "Indian Accent / 印度口音", | |
| "Korean Accent / 韩国口音", | |
| "Portuguese Accent / 葡萄牙口音", | |
| "Russian Accent / 俄罗斯口音", | |
| "Japanese Accent / 日本口音", | |
| ], | |
| "Chinese Dialect / 中文方言": [ | |
| "Henan Dialect / 河南话", | |
| "Shaanxi Dialect / 陕西话", | |
| "Sichuan Dialect / 四川话", | |
| "Guizhou Dialect / 贵州话", | |
| "Yunnan Dialect / 云南话", | |
| "Guilin Dialect / 桂林话", | |
| "Jinan Dialect / 济南话", | |
| "Shijiazhuang Dialect / 石家庄话", | |
| "Gansu Dialect / 甘肃话", | |
| "Ningxia Dialect / 宁夏话", | |
| "Qingdao Dialect / 青岛话", | |
| "Northeast Dialect / 东北话", | |
| ], | |
| } | |
| _ATTR_INFO = { | |
| "English Accent / 英文口音": "Only effective for English speech.", | |
| "Chinese Dialect / 中文方言": "Only effective for Chinese speech.", | |
| } | |
| # --------------------------------------------------------------------------- | |
| # Argument parser | |
| # --------------------------------------------------------------------------- | |
| def build_parser() -> argparse.ArgumentParser: | |
| parser = argparse.ArgumentParser( | |
| prog="omnivoice-demo", | |
| description="Launch a Gradio demo for OmniVoice.", | |
| formatter_class=argparse.RawTextHelpFormatter, | |
| ) | |
| parser.add_argument( | |
| "--model", | |
| default="k2-fsa/OmniVoice", | |
| help="Model checkpoint path or HuggingFace repo id.", | |
| ) | |
| parser.add_argument( | |
| "--device", default=None, help="Device to use. Auto-detected if not specified." | |
| ) | |
| parser.add_argument("--ip", default="0.0.0.0", help="Server IP (default: 0.0.0.0).") | |
| parser.add_argument( | |
| "--port", type=int, default=7860, help="Server port (default: 7860)." | |
| ) | |
| parser.add_argument( | |
| "--root-path", | |
| default=None, | |
| help="Root path for reverse proxy.", | |
| ) | |
| parser.add_argument( | |
| "--share", action="store_true", default=False, help="Create public link." | |
| ) | |
| parser.add_argument( | |
| "--no-asr", | |
| action="store_true", | |
| default=False, | |
| help="Skip loading Whisper ASR model. Reference text auto-transcription" | |
| " will be unavailable.", | |
| ) | |
| parser.add_argument( | |
| "--asr-model", | |
| default="openai/whisper-large-v3-turbo", | |
| help="ASR model path or HuggingFace repo id" | |
| " (default: openai/whisper-large-v3-turbo).", | |
| ) | |
| return parser | |
| # --------------------------------------------------------------------------- | |
| # Build demo | |
| # --------------------------------------------------------------------------- | |
| def build_demo( | |
| model: OmniVoice, | |
| checkpoint: str, | |
| generate_fn=None, | |
| ) -> gr.Blocks: | |
| sampling_rate = model.sampling_rate | |
| # -- shared generation core -- | |
| def _gen_core( | |
| text, | |
| language, | |
| ref_audio, | |
| instruct, | |
| num_step, | |
| guidance_scale, | |
| denoise, | |
| speed, | |
| duration, | |
| preprocess_prompt, | |
| postprocess_output, | |
| mode, | |
| ref_text=None, | |
| ): | |
| if not text or not text.strip(): | |
| return None, "Please enter the text to synthesize." | |
| gen_config = OmniVoiceGenerationConfig( | |
| num_step=int(num_step or 32), | |
| guidance_scale=float(guidance_scale) if guidance_scale is not None else 2.0, | |
| denoise=bool(denoise) if denoise is not None else True, | |
| preprocess_prompt=bool(preprocess_prompt), | |
| postprocess_output=bool(postprocess_output), | |
| ) | |
| lang = language if (language and language != "Auto") else None | |
| kw: Dict[str, Any] = dict( | |
| text=text.strip(), language=lang, generation_config=gen_config | |
| ) | |
| if speed is not None and float(speed) != 1.0: | |
| kw["speed"] = float(speed) | |
| if duration is not None and float(duration) > 0: | |
| kw["duration"] = float(duration) | |
| if mode == "clone": | |
| if not ref_audio: | |
| return None, "Please upload a reference audio." | |
| kw["voice_clone_prompt"] = model.create_voice_clone_prompt( | |
| ref_audio=ref_audio, | |
| ref_text=ref_text, | |
| ) | |
| if instruct and instruct.strip(): | |
| kw["instruct"] = instruct.strip() | |
| try: | |
| audio = model.generate(**kw) | |
| except Exception as e: | |
| return None, f"Error: {type(e).__name__}: {e}" | |
| waveform = (audio[0] * 32767).astype(np.int16) | |
| return (sampling_rate, waveform), "Done." | |
| # Allow external wrappers (e.g. spaces.GPU for ZeroGPU Spaces) | |
| _gen = generate_fn if generate_fn is not None else _gen_core | |
| # ===================================================================== | |
| # UI | |
| # ===================================================================== | |
| theme = gr.themes.Soft( | |
| font=["Inter", "Arial", "sans-serif"], | |
| ) | |
| css = """ | |
| .gradio-container {max-width: 100% !important; font-size: 16px !important;} | |
| .gradio-container h1 {font-size: 1.5em !important;} | |
| .gradio-container .prose {font-size: 1.1em !important;} | |
| .compact-audio audio {height: 60px !important;} | |
| .compact-audio .waveform {min-height: 80px !important;} | |
| """ | |
| # Reusable: language dropdown component | |
| def _lang_dropdown(label="Language (optional) / 语种 (可选)", value="Auto"): | |
| return gr.Dropdown( | |
| label=label, | |
| choices=_ALL_LANGUAGES, | |
| value=value, | |
| allow_custom_value=False, | |
| interactive=True, | |
| info="Keep as Auto to auto-detect the language.", | |
| ) | |
| # Reusable: optional generation settings accordion | |
| def _gen_settings(): | |
| with gr.Accordion("Generation Settings (optional)", open=False): | |
| sp = gr.Slider( | |
| 0.5, | |
| 1.5, | |
| value=1.0, | |
| step=0.05, | |
| label="Speed", | |
| info="1.0 = normal. >1 faster, <1 slower. Ignored if Duration is set.", | |
| ) | |
| du = gr.Number( | |
| value=None, | |
| label="Duration (seconds)", | |
| info=( | |
| "Leave empty to use speed." | |
| " Set a fixed duration to override speed." | |
| ), | |
| ) | |
| ns = gr.Slider( | |
| 4, | |
| 64, | |
| value=32, | |
| step=1, | |
| label="Inference Steps", | |
| info="Default: 32. Lower = faster, higher = better quality.", | |
| ) | |
| dn = gr.Checkbox( | |
| label="Denoise", | |
| value=True, | |
| info="Default: enabled. Uncheck to disable denoising.", | |
| ) | |
| gs = gr.Slider( | |
| 0.0, | |
| 4.0, | |
| value=2.0, | |
| step=0.1, | |
| label="Guidance Scale (CFG)", | |
| info="Default: 2.0.", | |
| ) | |
| pp = gr.Checkbox( | |
| label="Preprocess Prompt", | |
| value=True, | |
| info="apply silence removal and trimming to the reference " | |
| "audio, add punctuation in the end of reference text (if not already)", | |
| ) | |
| po = gr.Checkbox( | |
| label="Postprocess Output", | |
| value=True, | |
| info="Remove long silences from generated audio.", | |
| ) | |
| return ns, gs, dn, sp, du, pp, po | |
| with gr.Blocks(theme=theme, css=css, title="OmniVoice Demo") as demo: | |
| gr.Markdown( | |
| """ | |
| # OmniVoice Demo | |
| State-of-the-art text-to-speech model for **600+ languages**, supporting: | |
| - **Voice Clone** — Clone any voice from a reference audio | |
| - **Voice Design** — Create custom voices with speaker attributes | |
| Built with [OmniVoice](https://github.com/k2-fsa/OmniVoice) | |
| by Xiaomi AI Lab Next-gen Kaldi team. | |
| """ | |
| ) | |
| with gr.Tabs(): | |
| # ============================================================== | |
| # Voice Clone | |
| # ============================================================== | |
| with gr.TabItem("Voice Clone"): | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| vc_text = gr.Textbox( | |
| label="Text to Synthesize / 待合成文本", | |
| lines=4, | |
| placeholder="Enter the text you want to synthesize...", | |
| ) | |
| vc_ref_audio = gr.Audio( | |
| label="Reference Audio / 参考音频", | |
| type="filepath", | |
| elem_classes="compact-audio", | |
| ) | |
| gr.Markdown( | |
| "<span style='font-size:0.85em;color:#888;'>" | |
| "Recommended: 3–10 seconds audio. " | |
| "</span>" | |
| ) | |
| vc_ref_text = gr.Textbox( | |
| label=("Reference Text (optional)" " / 参考音频文本(可选)"), | |
| lines=2, | |
| placeholder="Transcript of the reference audio. Leave empty" | |
| " to auto-transcribe via ASR models.", | |
| ) | |
| vc_lang = _lang_dropdown("Language (optional) / 语种 (可选)") | |
| with gr.Accordion("Instruct (optional)", open=False): | |
| vc_instruct = gr.Textbox(label="Instruct", lines=2) | |
| ( | |
| vc_ns, | |
| vc_gs, | |
| vc_dn, | |
| vc_sp, | |
| vc_du, | |
| vc_pp, | |
| vc_po, | |
| ) = _gen_settings() | |
| vc_btn = gr.Button("Generate / 生成", variant="primary") | |
| with gr.Column(scale=1): | |
| vc_audio = gr.Audio( | |
| label="Output Audio / 合成结果", | |
| type="numpy", | |
| ) | |
| vc_status = gr.Textbox(label="Status / 状态", lines=2) | |
| def _clone_fn( | |
| text, lang, ref_aud, ref_text, instruct, ns, gs, dn, sp, du, pp, po | |
| ): | |
| return _gen( | |
| text, | |
| lang, | |
| ref_aud, | |
| instruct, | |
| ns, | |
| gs, | |
| dn, | |
| sp, | |
| du, | |
| pp, | |
| po, | |
| mode="clone", | |
| ref_text=ref_text or None, | |
| ) | |
| vc_btn.click( | |
| _clone_fn, | |
| inputs=[ | |
| vc_text, | |
| vc_lang, | |
| vc_ref_audio, | |
| vc_ref_text, | |
| vc_instruct, | |
| vc_ns, | |
| vc_gs, | |
| vc_dn, | |
| vc_sp, | |
| vc_du, | |
| vc_pp, | |
| vc_po, | |
| ], | |
| outputs=[vc_audio, vc_status], | |
| ) | |
| # ============================================================== | |
| # Voice Design | |
| # ============================================================== | |
| with gr.TabItem("Voice Design"): | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| vd_text = gr.Textbox( | |
| label="Text to Synthesize / 待合成文本", | |
| lines=4, | |
| placeholder="Enter the text you want to synthesize...", | |
| ) | |
| vd_lang = _lang_dropdown() | |
| _AUTO = "Auto" | |
| vd_groups = [] | |
| for _cat, _choices in _CATEGORIES.items(): | |
| vd_groups.append( | |
| gr.Dropdown( | |
| label=_cat, | |
| choices=[_AUTO] + _choices, | |
| value=_AUTO, | |
| info=_ATTR_INFO.get(_cat), | |
| ) | |
| ) | |
| ( | |
| vd_ns, | |
| vd_gs, | |
| vd_dn, | |
| vd_sp, | |
| vd_du, | |
| vd_pp, | |
| vd_po, | |
| ) = _gen_settings() | |
| vd_btn = gr.Button("Generate / 生成", variant="primary") | |
| with gr.Column(scale=1): | |
| vd_audio = gr.Audio( | |
| label="Output Audio / 合成结果", | |
| type="numpy", | |
| ) | |
| vd_status = gr.Textbox(label="Status / 状态", lines=2) | |
| def _build_instruct(groups): | |
| """Extract instruct text from UI dropdowns. | |
| Language unification and validation is handled by | |
| _resolve_instruct inside _preprocess_all. | |
| """ | |
| selected = [g for g in groups if g and g != "Auto"] | |
| if not selected: | |
| return None | |
| parts = [] | |
| for v in selected: | |
| if " / " in v: | |
| en, zh = v.split(" / ", 1) | |
| # Dialects have no English equivalent | |
| if "Dialect" in v.split(" / ")[0]: | |
| parts.append(zh.strip()) | |
| else: | |
| parts.append(en.strip()) | |
| else: | |
| parts.append(v) | |
| return ", ".join(parts) | |
| def _design_fn(text, lang, ns, gs, dn, sp, du, pp, po, *groups): | |
| return _gen( | |
| text, | |
| lang, | |
| None, | |
| _build_instruct(groups), | |
| ns, | |
| gs, | |
| dn, | |
| sp, | |
| du, | |
| pp, | |
| po, | |
| mode="design", | |
| ) | |
| vd_btn.click( | |
| _design_fn, | |
| inputs=[ | |
| vd_text, | |
| vd_lang, | |
| vd_ns, | |
| vd_gs, | |
| vd_dn, | |
| vd_sp, | |
| vd_du, | |
| vd_pp, | |
| vd_po, | |
| ] | |
| + vd_groups, | |
| outputs=[vd_audio, vd_status], | |
| ) | |
| return demo | |
| # --------------------------------------------------------------------------- | |
| # Main | |
| # --------------------------------------------------------------------------- | |
| def main(argv=None) -> int: | |
| logging.basicConfig( | |
| level=logging.INFO, | |
| format="%(asctime)s %(name)s %(levelname)s: %(message)s", | |
| ) | |
| parser = build_parser() | |
| args = parser.parse_args(argv) | |
| device = args.device or get_best_device() | |
| checkpoint = args.model | |
| if not checkpoint: | |
| parser.print_help() | |
| return 0 | |
| logging.info(f"Loading model from {checkpoint}, device={device} ...") | |
| model = OmniVoice.from_pretrained( | |
| checkpoint, | |
| device_map=device, | |
| dtype=torch.float16, | |
| load_asr=not args.no_asr, | |
| asr_model_name=args.asr_model, | |
| ) | |
| print("Model loaded.") | |
| demo = build_demo(model, checkpoint) | |
| demo.queue().launch( | |
| server_name=args.ip, | |
| server_port=args.port, | |
| share=args.share, | |
| root_path=args.root_path, | |
| ) | |
| return 0 | |
| if __name__ == "__main__": | |
| raise SystemExit(main()) | |