简体中文 | Installation | Model selection
from funasr import AutoModel runs models inside your Python process. It is not an HTTP client and does not implement the entire OpenAI API. This guide describes the implementation in this checkout, not every historical FunASR release or upstream checkpoint.
Construction and Inference Are Different
AutoModel(**kwargs) resolves a model configuration, looks up its registered implementation, loads weights, and optionally constructs VAD, punctuation, and speaker models. model.generate(input, input_len=None, progress_callback=None, **cfg) runs those already-loaded components. Passing a new model, vad_model, or device to generate() is not a supported way to rebuild or move the pipeline; construct a separate instance.
The wrapper accepts **kwargs, not a universally validated parameter schema. A keyword being accepted does not mean the selected model uses it. Configuration files can override the fallback defaults below. See AutoModel source, the registry, hub resolution, and alias maps.
Construction Parameters
| Parameter | Source fallback | Meaning |
|---|---|---|
model |
Required | Hub alias, full model ID, or complete local model directory. Aliases are hub-specific, not version pins. |
hub |
"ms" |
"ms"/"modelscope" or "hf"/"huggingface". The special "openai" loader branch concerns Whisper loading, not HTTP API compatibility. |
model_revision |
"master" in hub loaders |
ModelScope forwards the revision. The generic Hugging Face helper currently ignores it; see reproducibility below. |
device |
"cuda" |
E.g. "cuda:0" or "cpu". Unavailable checked accelerator backends fall back to CPU; explicit ngpu=0 does too. Fallback sets batch_size=1. |
ngpu |
1 |
Zero selects CPU. This is not a multi-GPU serving or sharding configuration. |
ncpu |
4 |
Positive CPU thread count; invalid values use the fallback and values below 1 clamp to 1. Sets process-wide PyTorch threads. |
vad_model, punc_model, spk_model |
None |
Optional components, built once. Use vad_model, not the rejected typo vda_model. |
vad_kwargs, punc_kwargs, spk_kwargs |
{} |
Component configuration dictionaries. Device is inherited; hub and CPU threads are inherited unless provided in the component dictionary. |
vad_model_revision, punc_model_revision, spk_model_revision |
"master" each |
Separate component revisions, not inherited from the ASR revision. These top-level values replace model_revision in the component dictionaries. |
spk_mode |
"punc_segment" |
Use "punc_segment" or "vad_segment". The validation also accepts legacy "default", but the sentence-building branches do not implement it; do not select it. |
disable_update |
False |
Disables the FunASR package version check only, not model downloading. |
disable_pbar |
False |
Suppresses wrapper progress bars. |
trust_remote_code |
False in hub loaders |
Opt-in to model-supplied requirements and code paths. Review the exact files and dependencies first. |
Per-Call Parameters
| Parameter | Source fallback | Scope and limits |
|---|---|---|
input |
Required | Audio path, URL, waveform, supported audio bytes, or a list of inputs. Text models such as punctuation accept text. |
input_len |
None |
The direct inference wrapper forwards it as data_lengths only for a single data_type="fbank" input; it is not a universal waveform-length control. |
progress_callback |
None |
callback(current, total) after direct inference batches. VAD processing can forward it to component calls; it is not one global monotonic pipeline progress counter. |
batch_size |
1 |
Number of inputs per direct inference call. Actual model batch support varies. |
batch_size_s |
300 |
VAD-path batching budget in seconds, based on longest padded segment times segment count, not a hard file-duration limit. CPU VAD processing uses single-segment batches. |
batch_size_threshold_s |
60 |
VAD batching threshold for segment duration, not a VAD splitting setting. |
merge_vad |
False |
Enables merging detected VAD regions for this call. |
merge_length_s |
15 |
VAD merge target read before call overrides are merged into ASR config. Set this at construction in this checkout. |
cache |
No wrapper-managed session | Pass a caller-owned dictionary on every streaming call. It is not a hub/model download cache. |
sentence_timestamp |
False |
Requests sentence records in the VAD pipeline; depends on available timestamps and punctuation, with limited VAD fallback. |
return_spk_res |
True |
Includes clustered speaker results when VAD and a speaker model are configured. False does not avoid construction or segment embedding computation. |
preset_spk_num |
None |
Optional speaker-count hint for the clustering backend. |
return_spk_center |
False |
Adds spk_embedding_center when clustering runs. Array-valued output may need conversion before JSON serialization. |
return_raw_text |
False |
Preserves pre-punctuation text where punctuation is applied; does not guarantee this field on every path. |
generate() restores saved construction configuration before merging call options. Repeat request-specific options on each call; do not rely on the previous call's language, batch settings, or hotwords. This configuration reset does not establish thread safety or reset every model attribute: for example, a speaker-mode fallback mutates self.spk_mode. Serialize access to a shared instance unless your own concurrency tests establish otherwise.
Local Files and Batching
Install the SDK using the installation guide. The three examples below are standalone scripts with command-line arguments and require prepared local model snapshots and real audio. Their syntax and wrapper contracts are checked without downloading weights; they are not reported as full inference tests.
For this example, invoke the script with a local ASR directory followed by one or more audio paths, for example python transcribe.py /models/paraformer recording.wav recording2.wav. The checks fail before model construction if those paths do not exist.
import argparse
from pathlib import Path
from funasr import AutoModel
parser = argparse.ArgumentParser()
parser.add_argument("model_dir")
parser.add_argument("audio", nargs="+")
args = parser.parse_args()
model_dir = Path(args.model_dir).expanduser().resolve(strict=True)
if not model_dir.is_dir():
raise ValueError("model_dir must be a complete local model directory")
audio = [str(Path(path).expanduser().resolve(strict=True)) for path in args.audio]
model = AutoModel(model=str(model_dir), device="cpu", disable_update=True)
results = model.generate(input=audio, batch_size=1)
for result in results:
print(result.get("key"), result.get("text", ""))
batch_size=1 processes a list serially through direct inference; raise it only for a model that supports batching and after measuring memory use. batch_size_s has a different meaning and only controls the wrapper's VAD path. VAD segmentation is not incremental microphone streaming, and it does not guarantee unlimited recording length or bounded total memory.
Use a one-dimensional mono float32 waveform with a known sample rate. For models using the common audio loader, fs in generate() describes the array's source sample rate (fallback 16000); the model frontend supplies the target rate. Do not pass a stereo matrix or a list of numbers and assume it will be treated as one waveform: a Python list is normally a list of inputs. File decoding depends on the installed audio backends. Top-level bytes are handled by load_bytes: recognized containers are decoded/resampled to 16 kHz, otherwise bytes are interpreted as int16 PCM without sample-rate metadata. Prefer a decoded array with an explicit rate for ambiguous inputs. See audio loading and byte-input tests.
prepare_data_iterator also accepts manifests. A .scp line can be utterance_id /path/to/audio.wav; .jsonl records use {"source": "/path/to/audio.wav", "key": "utterance_id"}. .json is not parsed as an arbitrary JSON array by this iterator. Do not expose unrestricted paths or URLs directly to untrusted callers.
VAD, Timestamps, and Speakers
Run this pipeline example with ASR, VAD, punctuation, speaker directories, then audio, in that order. It is intended for a compatible local Paraformer/SeACo-Paraformer, FSMN-VAD, CT-Transformer punctuation, and CAM++ setup, not every model combination.
import argparse
from pathlib import Path
from funasr import AutoModel
parser = argparse.ArgumentParser()
for name in ("asr_dir", "vad_dir", "punc_dir", "spk_dir", "audio"):
parser.add_argument(name)
args = parser.parse_args()
paths = {name: Path(value).expanduser().resolve(strict=True)
for name, value in vars(args).items()}
if not all(paths[name].is_dir() for name in ("asr_dir", "vad_dir", "punc_dir", "spk_dir")):
raise ValueError("All model arguments must be complete local directories")
model = AutoModel(
model=str(paths["asr_dir"]),
vad_model=str(paths["vad_dir"]),
punc_model=str(paths["punc_dir"]),
spk_model=str(paths["spk_dir"]),
spk_mode="punc_segment",
device="cpu",
disable_update=True,
)
for result in model.generate(input=str(paths["audio"]), return_spk_res=True):
print(result.get("text", ""))
for sentence in result.get("sentence_info", []):
print(sentence.get("start"), sentence.get("end"),
sentence.get("spk"), sentence.get("text", ""))
With vad_model configured, the wrapper detects regions, sorts them by duration for ASR batching, restores their order, and offsets timestamps to the original recording. Generic speaker clustering runs in this VAD path; setting only spk_model does not add diarization to direct inference. punc_segment needs usable punctuation and timestamps; missing punctuation or timestamp fields can change the mode to vad_segment. VAD boundaries are speech-region boundaries, not necessarily speaker changes. Labels such as spk=0 are anonymous within a result, not verified identities or stable IDs across recordings.
For sentence_timestamp=True without speakers, the current wrapper can return VAD-aligned sentence records when both punctuation and token timestamps are absent, or when punctuation/timestamp lengths fail alignment. Other combinations can return an empty sentence_info, including timestamps present but no punctuation result. This flag does not create a forced aligner.
Result Fields
generate() returns a Python list of model-result dictionaries, not an OpenAI response object. Do not assume every model produces every field, or index results[0] without checking: some VAD empty-text paths can skip a result. No-speech VAD results commonly contain {"key": ..., "text": "", "timestamp": []}.
| Field | Meaning |
|---|---|
key |
Input identifier, often a file stem or manifest key. Random keys are generated in other cases; they are not guaranteed globally unique. |
text |
Decoded text. May contain model-specific rich tags; it is not necessarily plain display text. |
timestamp |
When produced by the ASR paths described here: token/word/character interval pairs [[start_ms, end_ms], ...]. Granularity and availability depend on model/checkpoint. |
timestamps |
Nano's CTC-backed alignment can produce dictionaries with token, start_time, end_time in seconds. VAD merging offsets these and can also add millisecond timestamp pairs. |
sentence_info |
Pipeline sentence dictionaries with start/end in milliseconds, text, optional timestamp, and spk when speaker assignment runs. Some paths also include sentence. |
raw_text |
Optional pre-punctuation text, not a guaranteed untouched copy after all possible processing. |
value |
A standalone VAD model's speech intervals, not ASR text. Online VAD can emit incomplete boundaries; follow that model's streaming protocol. |
Additional fields such as words, ctc_timestamps, or speaker embeddings are model-specific. Do not relabel SDK milliseconds as service seconds without conversion. See timestamp regression tests and the model sources below.
Language, Hotwords, and Alignment Are Model-Specific
| Implementation | Runtime controls in this checkout |
|---|---|
| SeACo-Paraformer | hotword (singular), fallback None: a whitespace-separated string, local .txt path, or supported URL. This parser expects a string, not Nano's list form. The paraformer-zh ModelScope alias maps to this implementation's checkpoint. |
| Paraformer | pred_timestamp takes precedence when supplied; otherwise output_timestamp falls back to False. A checkpoint's saved options may enable timestamps. Do not generalize one Paraformer variant's hotword/timestamp behavior to all variants. |
| SenseVoice | language="auto"; language tokens include zh, en, yue, ja, ko. Unknown hints fall back to the auto token. use_itn=False; explicit text_norm overrides it. output_timestamp=False; enabling it uses this implementation's CTC alignment path. Generic decoder hotwords are not consumed here. |
| Fun-ASR-Nano | hotwords=[] (plural, list of strings), language=None, itn=True. Language is inserted into a text prompt, not normalized through the SenseVoice token table. CTC timestamps depend on loaded components and complete checkpoint weights, not just an output flag. |
| Qwen3-ASR adapter | language=None; auto becomes None, and implemented ISO aliases such as zh/en map to full language names. context="" is the contextual prompt, not hotword. return_time_stamps=False or output_timestamp=False; either enables a request for timestamps, but a forced_aligner must have been configured at construction. Without it, the adapter warns and skips timestamps. |
These are control conventions, not promises of language coverage, accuracy, or identical checkpoint contents across hubs. Nano disables CTC output when required tensors are missing; see checkpoint validation. MOSS-Transcribe-Diarize is a third-party OpenMOSS model with native joint transcription/diarization and a separate schema/dependency path: use the MOSS guide, not the external VAD/CAM++ example above.
Text-Level Hotword Correction
The wrapper also supports postprocess_hotwords (string/list/dict) and postprocess_hotword_file in generate(). Explicit mappings can use {"wrong": "right"} or a file line wrong=>right. postprocess_hotword_threshold=0.85, postprocess_hotword_fuzzy=True, and return_postprocess_hotword_matches=False are the fallbacks. Fuzzy matching may require pypinyin and rapidfuzz; setting postprocess_hotword_fuzzy=False selects explicit replacement only.
This runs after decoding, updates text and sentence text, and intentionally leaves timestamps aligned to the original recognition. It neither biases the acoustic decoder nor re-aligns replacements. Inspect replacement details before using corrected text for word-level subtitles. Pass these options per call: generate() sends its cfg, not the construction defaults, to this postprocessor. See implementation and tests.
Streaming Cache Lifecycle
The following example is specifically for the local Paraformer streaming checkpoint, not an offline ASR model made streaming by cache={}. Invoke it with the model directory and a nonempty mono 16 kHz audio file. It follows the upstream repository demo and streaming implementation.
import argparse
from pathlib import Path
import soundfile as sf
from funasr import AutoModel
parser = argparse.ArgumentParser()
parser.add_argument("model_dir")
parser.add_argument("audio")
args = parser.parse_args()
model_dir = Path(args.model_dir).expanduser().resolve(strict=True)
if not model_dir.is_dir():
raise ValueError("model_dir must be a complete local streaming model directory")
speech, sample_rate = sf.read(args.audio, dtype="float32")
if sample_rate != 16000 or speech.ndim != 1 or len(speech) == 0:
raise ValueError("Expected nonempty mono 16 kHz audio")
model = AutoModel(model=str(model_dir), device="cpu", disable_update=True)
chunk_size = [0, 10, 5]
stride = chunk_size[1] * 960
cache = {}
for start in range(0, len(speech), stride):
end = min(start + stride, len(speech))
result = model.generate(
input=speech[start:end], cache=cache, is_final=end == len(speech),
chunk_size=chunk_size, encoder_chunk_look_back=4,
decoder_chunk_look_back=1, batch_size=1,
)
print(result)
For this implementation, chunk_size falls back to [0, 10, 5] and is_final to False. The middle value times 960 gives the input stride: 9600 samples at 16 kHz is 600 ms. Both encoder_chunk_look_back and decoder_chunk_look_back default to 0 in source; 4 and 1 above are explicit demo settings, not wrapper defaults.
Create a new cache={} per stream, pass the same dictionary on every ordered chunk, keep chunk/look-back settings fixed, and set is_final=True on the last chunk to flush buffered state. Paraformer streaming currently reinitializes its cache after finalization; discard it anyway when ending, cancelling, or starting a different stream. Do not share caches across recordings or simultaneous users. Keep batch_size=1: this implementation asserts one waveform per call. Returned text is for the decoded chunks in that call, not a guaranteed cumulative transcript; retain outputs in the application. WebSocket session protocols and server-side buffering are separate from this dictionary lifecycle.
Reproducibility and Offline Use
- Pin the SDK version/commit and dependency versions separately from model artifacts. Record the hub, full model ID, resolved upstream revision, configuration, and weight hashes for ASR and every auxiliary model. An alias or moving
masteris not a reproducible pin. - The generic ModelScope loader forwards
model_revisionto its snapshot downloader. The generic Hugging Face helper accepts it but currently callssnapshot_download(model), withoutrevision,local_files_only, orcheck_latest. Do not claimhub="hf", model_revision=...pins that path. Some model adapters have their own loading logic; inspect the selected adapter too. - For offline operation, prepare and verify complete local snapshots while online, including tokenizer/frontend files, configuration, weights, nested encoders/LLMs, and optional aligners. Pass existing local directories for all components. Local paths bypass generic hub resolution, but nested model code can still contact services or need missing dependencies; test under an actual network restriction.
disable_update=Trueonly skips the package update check.check_latest=Falseis not an offline guarantee, and these generic helpers do not provide a universallocal_files_onlyswitch. URL audio and URL hotword inputs still require network access. Cached hub aliases may still trigger hub requests.- Keep
trust_remote_code=Falseunless audited model code requires otherwise. ModelScope's generic loader can importremote_code(default"model") when trusted; both generic hub loaders can install a model'srequirements.txtwhen trusted, while their code-import behavior is not identical. A local snapshot is not automatically safe code.
The FunASR software is MIT-licensed; model weights, datasets, third-party adapters, and dependencies can have different licenses. Review the selected model's own license and usage conditions before redistribution or deployment.
SDK and Service Boundaries
| Interface | Contract to use |
|---|---|
Python AutoModel |
In-process model configuration, waveform inputs, streaming dictionaries, and model-specific Python results described here. No base_url, API key, or HTTP response_format contract. |
funasr-server |
Packaged CLI creates the server app. Its /v1/audio/transcriptions endpoint is an OpenAI-style speech subset; /asr is a separate service-specific endpoint. Form fields, defaults, units, and speaker behavior belong to that server, not generate(). |
| Example OpenAI-compatible server | The example server is a different implementation from the packaged app. Use its OpenAPI reference, client recipes, and security/gateway guide, then compare the deployed server's live /openapi.json. Do not assume their defaults or response fields are identical. |
| vLLM | AutoModelVLLM, FunASR's model-specific services, and native vllm serve are distinct entry points. Neither the SDK's cache nor a transcription HTTP endpoint proves realtime-session compatibility. Follow the vLLM guide for the chosen route and checkpoint format. |
| llama.cpp / GGUF | Separate C++ executables and GGUF artifacts, not the Python AutoModel kwargs or result schema. Use the runtime guide. VAD alone is not speaker diarization. |
The Hydra inference entry point constructs AutoModel from configuration and calls generate(); it does not turn every CLI/config key into an HTTP form field. Before exposing any service, enforce authentication, TLS, upload limits, timeouts, and access restrictions at the appropriate boundary. A placeholder OpenAI-client API key is not access control.