([简体中文](./README_zh.md) | English)
# Python SDK tutorial
> **Only need native Fun-ASR-Nano transcription?** Start with [Transformers 5.17.0](../transformers_native.md). It loads the separate `-hf` checkpoint without the FunASR toolkit. This page covers the `funasr.AutoModel` toolkit path; do not mix dependencies, parameters or output contracts.
Start with [installation and environment verification](../installation/installation.md). This path covers one transcript, result inspection, VAD, batching, and model-specific options. For model selection, languages, dependencies, and model cards, use the [Model Zoo](../../model_zoo/readme.md), not a universal capability list. No local setup yet? See the [Colab quickstart](../../examples/colab/README.md).
FunASR software uses the [MIT license](../../LICENSE). Each model weight has its own license: record the full model ID and revision, and follow its model card. The [FunASR Model License Agreement](../../MODEL_LICENSE) applies only when the model card explicitly links to it. Third-party integrations remain third-party models; for example, MOSS-Transcribe-Diarize is from OpenMOSS, not a FunASR-trained checkpoint.
## 1. Produce a first transcript
Run the following Python block after installing the SDK and a matching PyTorch/torchaudio environment. The first run needs network access for the model and this public example WAV, plus sufficient disk and memory. It is based on the repository's [Paraformer example](../../examples/industrial_data_pretraining/paraformer/demo.py); it is not a recorded inference result from this documentation review.
```python
from funasr import AutoModel
audio = "https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/test_audio/asr_example_zh.wav"
model = AutoModel(
model="paraformer-zh", hub="ms", device="cpu", ncpu=4,
disable_update=True, trust_remote_code=False,
)
results = model.generate(input=audio)
for item in results:
print(item.get("key"), item.get("text", ""))
print("Model directory:", model.model_path)
```
To transcribe your recording, replace `audio` with an existing local WAV path. Start with a short mono recording matching the selected model's sample rate (16 kHz for this example). File decoding depends on installed audio backends; a readable WAV is a simpler first check than an arbitrary media container. NumPy waveform input has no sample-rate header: supply the actual rate with `fs=sample_rate`, as used by the [audio loader](../../funasr/utils/load_utils.py). Do not merely relabel a waveform's rate.
The remaining Python blocks reuse `AutoModel`, `audio`, and `model` from this first block in the same session. For disconnected use, prepare complete local model directories and local input files using the [offline checklist](../installation/installation.md). `disable_update=True` only skips the SDK's startup version check.
## 2. Understand parameters and results
`AutoModel(...)` constructs the model and optional pipeline components. `model.generate(input=..., **options)` performs inference. Source references: [AutoModel](../../funasr/auto/auto_model.py), [hub aliases](../../funasr/download/name_maps_from_hub.py), and the chosen model's `inference()` implementation.
| Parameter | Scope and meaning |
| --- | --- |
| `model`, `hub` | Model ID/alias or local directory; hub defaults to ModelScope (`ms`), with `hf` for Hugging Face. Aliases can resolve to different hub repositories. |
| `device`, `ncpu` | Explicitly use `cpu` to begin; choose an accelerator only after validating its PyTorch build and model support. The loader has CPU fallback paths; `ncpu` controls PyTorch CPU threads. |
| `vad_model`, `punc_model`, `spk_model` | Optional, separately loaded models. Configure them through `vad_kwargs`, `punc_kwargs`, and `spk_kwargs`. They are not automatically supported by every ASR backend. |
| `batch_size` | Number of inputs per decoding batch on the ordinary non-VAD path; backend restrictions still apply. |
| `batch_size_s` | Duration budget in seconds for VAD-segment batching, based on padded segment length, not a count of files. The current CPU VAD path decodes segments individually. |
| `batch_size_threshold_s` | Segment-duration threshold used by the VAD batching heuristic; not an input duration limit or a universal memory cap. |
| `output_dir` | Optional backend output directory. The returned Python result is still available; files and formats depend on the model. |
`generate()` returns a list of dictionaries, normally one per input recording. Inspect keys before depending on optional fields:
```python
for item in results:
print(sorted(item.keys()))
print(item.get("text", ""))
print(item.get("timestamp", []))
```
For the Paraformer path, `timestamp` contains character/token/word intervals as `[start_ms, end_ms]` pairs when supplied by the checkpoint. Do not assume one pair per displayed character after punctuation or text normalization. Other backends may return `timestamps` with a different schema; follow that backend's guide. Empty speech may produce empty text/timestamps, not a meaningful transcript.
## 3. Add VAD, punctuation, and sentence timestamps
VAD detects speech spans; it does not transcribe them. This standalone call uses the same audio:
```python
vad = AutoModel(model="fsmn-vad", device="cpu", disable_update=True)
vad_results = vad.generate(input=audio)
for item in vad_results:
print(item["key"], item["value"])
```
`value` is a list of `[start_ms, end_ms]` speech intervals relative to the recording start. An empty list means no detected spans. See the [FSMN VAD example](../../examples/industrial_data_pretraining/fsmn_vad_streaming/demo.py).
For segmented ASR with punctuation:
```python
pipeline = AutoModel(
model="paraformer-zh", vad_model="fsmn-vad", punc_model="ct-punc",
vad_kwargs={"max_single_segment_time": 30000},
device="cpu", disable_update=True, trust_remote_code=False,
)
segmented_results = pipeline.generate(
input=audio, batch_size_s=60, batch_size_threshold_s=30,
sentence_timestamp=True,
)
for item in segmented_results:
print(item.get("text", ""))
for sentence in item.get("sentence_info", []):
print(sentence.get("start"), sentence.get("end"), sentence.get("text", ""))
```
`max_single_segment_time` is in **milliseconds**; the two batching controls are in **seconds**. Segmentation can help with longer files but does not guarantee unlimited duration or bounded memory: the audio-loading stage and each model still consume resources. On memory pressure, use shorter recordings/segments and smaller supported batches, then measure again. Sentence boundaries depend on available timestamp/punctuation alignment and may fall back to VAD segments; inspect the returned data.
For diarization, construct the same pipeline with `spk_model="cam++"` if supported by the chosen components. Iterate each input's `item.get("sentence_info", [])`, then read `sentence.get("spk")`. Do not read `spk` directly from the outer result list. Cluster labels are not verified real-world identities. [Speaker integration example](../../examples/industrial_data_pretraining/sense_voice/demo_spk.py).
## 4. Process multiple recordings
The following deliberately repeats the sample to demonstrate a list input without requiring extra files. Replace the entries with your local WAV paths:
```python
batch_results = model.generate(input=[audio, audio], batch_size=1)
for index, item in enumerate(batch_results):
print(index, item.get("key"), item.get("text", ""))
```
Increase `batch_size` only if the selected model supports it and memory permits. A file list such as `wav.scp` is also supported: use one `utterance_id path` per line, resolve paths from the process working directory, and give each recording a unique ID. Set `output_dir` if you need model-written artifacts; it is not required simply to receive the returned list. See [data-list examples](../../data/list/train_wav.scp). Do not confuse independent file batching with streaming chunks of one utterance.
## 5. Hotwords and language boundaries
The ModelScope `paraformer-zh` alias in this checkout resolves to a SeACo Paraformer model, whose implementation accepts singular `hotword` as a space-separated string:
```python
biased_results = model.generate(input=audio, hotword="魔搭 达摩院")
print([item.get("text", "") for item in biased_results])
```
This is model-level context biasing, not guaranteed word insertion or deterministic replacement. Verify the resolved model and compare against a no-hotword baseline. [SeACo implementation](../../funasr/models/seaco_paraformer/model.py) and [contextual Paraformer example](../../examples/industrial_data_pretraining/contextual_paraformer/demo.py).
Postprocessing is a different operation in this source checkout:
```python
corrected_results = model.generate(
input=audio,
postprocess_hotwords={"科大迅飞": "科大讯飞"},
return_postprocess_hotword_matches=True,
)
for item in corrected_results:
print(item.get("text", ""), item.get("postprocess_hotword_matches", []))
```
Explicit mappings replace matching output text. `postprocess_hotword_file` also accepts one target per line or `wrong=>right` mappings. Fuzzy matching additionally needs `pypinyin` and `rapidfuzz`; explicit mappings do not. The [postprocessor](../../funasr/utils/postprocess_hotwords.py) preserves existing timestamps rather than realigning corrected text, so review replacements before making subtitles or alignment claims.
`hotword`, `hotwords`, and `language` are **not interchangeable universal SDK options**. For example, [Fun-ASR-Nano](../../examples/industrial_data_pretraining/fun_asr_nano/README.md) reads plural `hotwords` and a model-specific language hint. Changing a hint does not turn a monolingual checkpoint into a multilingual one. Use the [Model Zoo](../../model_zoo/readme.md) and the exact checkpoint guide for supported languages, accepted hint values, streaming, alignment, and dependency versions. Avoid copying language counts or installation pins between model families.
## 6. Continue with a specific workflow
- **Streaming:** [Paraformer streaming example](../../examples/industrial_data_pretraining/paraformer_streaming/demo.py). Keep a separate `cache={}` per stream and set `is_final=True` for the final chunk. For `[0, 10, 5]` at 16 kHz, 600 ms is **9600 samples**, not 960; chunk duration is not an end-to-end latency guarantee. Streaming VAD may return `[start, -1]`, `[-1, end]`, complete spans, or no spans, in milliseconds.
- **Punctuation and alignment:** [punctuation example](../../examples/industrial_data_pretraining/ct_transformer/demo.py) and [timestamp prediction example](../../examples/industrial_data_pretraining/monotonic_aligner/demo.py). Alignment needs the corresponding text input; it is not equivalent to ASR.
- **Other model families:** [SenseVoice](../../examples/industrial_data_pretraining/sense_voice/README.md), [Fun-ASR-Nano](../../examples/industrial_data_pretraining/fun_asr_nano/README.md), and [third-party OpenMOSS integration](../moss_transcribe_diarize.md). Discover further entries through the Model Zoo.
- **CLI and services:** [CLI reference](../cli.md), [runtime overview](../../runtime/readme.md), and [Docker](../installation/docker.md). Python options do not imply an identical server request schema.
## Model Training and Testing
Use the [Paraformer recipe](../../examples/industrial_data_pretraining/paraformer/README.md), [finetune.sh](../../examples/industrial_data_pretraining/paraformer/finetune.sh), and [training-data examples](../../data/list/train.jsonl). Inspect dataset paths, label alignment, model license, GPU allocation, and output directories before launching. Training is not an installation smoke test. For trained weights, inspect [infer_from_local.sh](../../examples/industrial_data_pretraining/paraformer/infer_from_local.sh): configuration, tokenizer/frontend assets, and checkpoint paths must agree. Keep [validation data](../../data/list/val.jsonl) separate from training data.
## Model Export and Testing
Follow the model's [Paraformer export example](../../examples/industrial_data_pretraining/paraformer/export.py) and [ONNX Runtime guide](../../runtime/python/onnxruntime/README.md). Export support and extra dependencies are model/backend-specific. Successful export is not evidence of output equivalence: test the exported artifact on representative inputs and compare with the original model before deployment.
## Register a Custom Model
Use the [registry tutorial](./Tables.md) and a real implementation such as [SenseVoice](../../funasr/models/sense_voice/model.py). Registration alone does not establish a working `generate()` contract; the model's inference result must match the downstream components it will use.
For failures, return to [troubleshooting](../troubleshooting.md) with interpreter/package versions, resolved model ID/revision, input format, and a minimal reproduction. Do not include private audio or credentials.