docs: clarify FunASR rolling context behavior

This commit is contained in:
2026-07-14 17:18:17 +08:00
parent 73c8a3416b
commit acfbd6d72a
3 changed files with 105 additions and 81 deletions
+1 -1
View File
@@ -132,7 +132,7 @@ uv run --directory SKILL_DIR/scripts/transcription funasr-nano VIDEO_PATH --list
Where `VIDEO_DIR` is the directory containing the video file, `SKILL_DIR` is the skill installation directory, and `AUDIO_LANGUAGE_CODE` is the explicit transcription language (for example `zh` for Mandarin Chinese).
**Context and hotwords:** Fun-ASR-Nano is an LLM-based ASR model and upstream code supports prompt-style `language` and `hotwords` hints. However, do not assume the current bundled script automatically performs cross-segment semantic correction: it currently passes `language` / `use_itn`, but does not pass external hotwords or rolling `prev_text` context between VAD segments. If the video contains known game terms, names, locations, item names, or other jargon, ask the user for a hotword list or derive candidate terms and confirm them before transcription. See `references/funasr-nano-context-hotwords.md`. Hotwords are biasing hints, not a substitute for final manual checking.
**Rolling context / semantic correction:** Fun-ASR-Nano has upstream support for `prev_text`-style rolling context in streaming/incremental examples: earlier stabilized text can be fed back as context for later decoding, similar to a 2-pass-style refinement. However, do not assume the current bundled offline script automatically enables whole-file rolling semantic correction: it currently calls ordinary `AutoModel.generate(...)` on the extracted WAV and does not run a cumulative chunked pass with `prev_text`. See `references/funasr-nano-rolling-context.md`. Treat the current transcript as a strong baseline, not the final word when unclear speech or homophones matter.
**Common OBS multi-track audio layouts.** When the user says "multi-track" or mentions OBS recording, these are the typical stream layouts:
@@ -1,80 +0,0 @@
# Fun-ASR-Nano context, hotwords, and transcript correction notes
Use this when deciding whether Fun-ASR-Nano can use semantic context to improve recognition quality.
## Verified from upstream code/docs
Sources checked:
- `modelscope/FunASR` `funasr/models/fun_asr_nano/model.py`
- `modelscope/FunASR` `funasr/models/fun_asr_nano/inference_vllm.py`
- `modelscope/FunASR` `funasr/models/fun_asr_nano/inference_vllm_pipeline.py`
- `modelscope/FunASR` `funasr/models/fun_asr_nano/inference_vllm_streaming.py`
- `modelscope/FunASR` `docs/vllm_guide_zh.md`
- `modelscope/FunASR` `docs/model_selection.md`
The upstream model is LLM-based: a SenseVoice-style audio encoder plus an LLM decoder. The upstream model-selection guide describes Fun-ASR-Nano as stronger on hard cases, context, and proper nouns.
The PyTorch path has a prompt builder roughly shaped as:
```python
def get_prompt(self, hotwords: list[str], language: str = None, itn: bool = True):
if len(hotwords) > 0:
prompt = "请结合上下文信息,更加准确地完成语音转写任务。如果没有相关信息,我们会留空。\n\n\n**上下文信息:**\n\n\n"
prompt += f"热词列表:[{hotwords}]\n"
else:
prompt = ""
if language is None:
prompt += "语音转写"
else:
prompt += f"语音转写成{language}"
if not itn:
prompt += ",不进行文本规整"
return prompt + ""
```
The vLLM path exposes the same idea via `hotwords` and `language`. The vLLM guide documents `language` and `hotwords` as `generate()` / API parameters.
## What is enabled by default?
Do **not** assume cross-segment semantic correction is automatically enabled for offline file transcription.
In the bundled transcription script at the time of writing:
- `funasr_common.py` calls `model.generate(input=..., batch_size=1)`.
- It passes `language` only when the user specified a non-`auto` language.
- It passes `use_itn=True` for Fun-ASR-Nano.
- It does **not** pass `hotwords`.
- It does **not** pass `prev_text` or a rolling context between VAD segments.
Therefore, the current script uses Nano's model-internal contextual ability, language hint, and ITN, but it does not provide external domain context or previous transcript text. The transcript may still contain homophone/near-homophone mistakes such as `帐篷` -> `账本` when the source audio is unclear.
## Practical guidance
1. Use explicit `--language AUDIO_LANGUAGE_CODE` to avoid language ambiguity.
2. If the content has known names, game terms, locations, item names, or recurring jargon, collect them as a hotword list before transcription.
3. Prefer adding explicit script support such as `--hotword TERM` / `--hotwords-file FILE` over relying on vague “semantic correction”.
4. Treat hotwords as biasing hints, not proof. They can improve proper nouns and domain terms but cannot fully fix unclear audio.
5. For final captions, quotes, subtitles, narration, or published copy, still re-listen and manually correct the original audio segment.
6. Do not silently invent hotwords. Ask the user for domain terms or extract candidate terms from existing project notes/transcripts and confirm them.
## Possible future script enhancement
Expose hotwords in the bundled CLI:
```bash
funasr-nano VIDEO_PATH \
--track TRACK_INDEX \
--language AUDIO_LANGUAGE_CODE \
--hotword "帐篷" \
--hotword "复活点" \
--output-dir VIDEO_DIR
```
Then pass them to FunASR:
```python
gen_kw["hotwords"] = args.hotwords
```
For longer lists, support a UTF-8 text file with one hotword per line.
+104
View File
@@ -0,0 +1,104 @@
# Fun-ASR-Nano rolling context / `prev_text` notes
Use this when deciding whether Fun-ASR-Nano can use already-transcribed context from the same audio file to improve later sentence recognition.
## User intent
This is **not** about manually adding fixed hotwords. The desired behavior is closer to rolling context or 2-pass-style refinement:
- While processing one independent audio/video file, the model should use text already recognized from earlier audio as context for later audio.
- When a current sentence is ambiguous because of unclear pronunciation, it may benefit from preceding vocabulary, phrasing, topic, and dialogue context.
- This is analogous to streaming ASR systems where early partial text may be wrong, and a later stabilized/final pass revises the sentence with more context.
## Verified upstream behavior
Sources checked:
- `modelscope/FunASR` `funasr/models/fun_asr_nano/model.py`
- `modelscope/FunASR` `examples/industrial_data_pretraining/fun_asr_nano/demo2.py`
- `modelscope/FunASR` `funasr/models/fun_asr_nano/inference_vllm_streaming.py`
- `modelscope/FunASR` `docs/vllm_guide.md`
- `modelscope/FunASR` `docs/vllm_guide_zh.md`
Fun-ASR-Nano supports a `prev_text` mechanism in the model inference path. In `model.py`, `prev_text` is appended into the assistant-side prompt prefix before decoding:
```python
if kwargs.get("prev_text", None) is not None:
source_input += kwargs["prev_text"]
```
The official `demo2.py` demonstrates cumulative chunk transcription:
```python
prev_text = ""
for idx, cum_duration in enumerate(cum_durations):
audio, rate = load_audio(wav_path, 16000, duration=round(cum_duration, 3))
prev_text = m.inference([torch.tensor(audio)], prev_text=prev_text, **kwargs)[0][0]["text"]
if idx != len(cum_durations) - 1:
prev_text = tokenizer.decode(tokenizer.encode(prev_text)[:-5]).replace("", "")
```
The streaming vLLM code also uses a two-stage design:
- Stage 1: generate early chunks without `prev_text` to find stable output.
- Stage 2: use stable output as `prev_text` for later cumulative chunks.
- It keeps a rollback/unfixed tail, so the last few characters may change as more audio arrives.
The vLLM guide explicitly describes this as:
- first chunks: no `prev_text`
- subsequent chunks: use stable output as `prev_text`
## What the current bundled script does
The current `scripts/transcription/funasr_common.py` path calls ordinary offline `AutoModel.generate(input=..., batch_size=1)` on the extracted WAV file.
It currently passes:
- `input`
- `batch_size=1`
- explicit `language` when non-`auto`
- `use_itn=True` for Fun-ASR-Nano
It does **not** currently implement a chunked/cumulative pass that feeds prior recognized text back through `prev_text`.
Therefore:
- Fun-ASR-Nano has model-level support for rolling text context.
- Upstream examples show this mechanism in streaming/incremental usage.
- But the current bundled offline script should **not** be described as automatically enabling whole-file rolling context correction.
## Practical implication for this skill
When accuracy matters, especially for unclear speech, homophones, game terms, and dialogue continuity, do not assume the default offline transcript is the best possible use of Nano's context mechanism.
The skill should describe this honestly:
1. Current default offline transcription is a strong baseline.
2. It may still produce wrong words such as `帐篷` -> `账本` when source speech is unclear.
3. Fun-ASR-Nano has `prev_text`/rolling-context mechanisms upstream, but the bundled script does not yet expose a stable offline mode for that.
4. A future enhancement can evaluate a chunked/cumulative or 2-pass-like transcription mode that feeds stabilized earlier text as `prev_text`.
5. Such a mode should be benchmarked before becoming default, because cumulative re-encoding may be slower and may have different timestamp/segmentation behavior.
## Future enhancement idea
A possible experimental mode:
```bash
funasr-nano VIDEO_PATH \
--track TRACK_INDEX \
--language AUDIO_LANGUAGE_CODE \
--context-mode rolling \
--rollback-chars 5 \
--output-dir VIDEO_DIR
```
Implementation direction:
- Split or cumulatively extend audio in chunks.
- Keep a stable prefix and an unfixed tail, similar to upstream `demo2.py` / streaming vLLM logic.
- Feed the stable prefix into `prev_text` for the next pass.
- Preserve a normal offline mode because it is simpler, faster, and already works.
- Compare quality on real user samples before enabling by default.
This is a transcription-mode experiment, not a hotword-list feature.