# How to Use PNC and ITN Toggles in transcribe.cpp: A Complete Guide

> Learn to use PNC and ITN toggles in transcribe.cpp for fine-tuned output formatting. This guide details runtime control via C API and CLI flags.

- Repository: [handy-computer/transcribe.cpp](https://github.com/handy-computer/transcribe.cpp)
- Tags: how-to-guide
- Published: 2026-07-21

---

**The transcribe.cpp library exposes PNC (punctuation/capitalization) and ITN (inverse text normalization) toggles through the `transcribe_run_params` structure, allowing you to control output formatting at runtime using the C API or CLI flags.**

The [`handy-computer/transcribe.cpp`](https://github.com/handy-computer/transcribe.cpp/blob/main/handy-computer/transcribe.cpp) repository provides runtime control over text normalization through two specific toggles in the transcription pipeline. These toggles determine whether the output includes proper punctuation and capitalization (PNC) and whether spoken numbers and dates convert to their written numeric forms (ITN). Understanding how to check feature support and set these parameters ensures your transcription results match your specific formatting requirements.

## Understanding PNC and ITN Features

**PNC (Punctuation and Capitalization)** controls whether the model output includes sentence capitalization and punctuation marks like periods and commas. **ITN (Inverse Text Normalization)** converts spoken forms—for example, "twenty twenty-four"—into their written equivalents, such as "2024."

These features are not universal across all model families. According to the source code in [`include/transcribe.h`](https://github.com/handy-computer/transcribe.cpp/blob/main/include/transcribe.h), the library defines feature flags `TRANSCRIBE_FEATURE_PNC` and `TRANSCRIBE_FEATURE_ITN` to advertise runtime capability. Model families like Canary and SenseVoice implement these toggles, while others such as Whisper ignore them entirely.

## Checking Model Feature Support

Before setting either toggle, verify that the loaded model supports the feature. The library provides the `transcribe_model_supports` function for this purpose.

If the model does not advertise support and you attempt to force-enable the feature, the library may emit error codes `TRANSCRIBE_ERR_UNSUPPORTED_PNC` or `TRANSCRIBE_ERR_UNSUPPORTED_ITN`, though these are currently defined but not actively returned by the implementation in [`src/transcribe.cpp`](https://github.com/handy-computer/transcribe.cpp/blob/main/src/transcribe.cpp).

```c
transcribe_model *model = transcribe_load_model("models/canary-1b-F32.gguf");

/* Check capability before setting parameters */
bool has_pnc = transcribe_model_supports(model, TRANSCRIBE_FEATURE_PNC);
bool has_itn = transcribe_model_supports(model, TRANSCRIBE_FEATURE_ITN);

```

## Setting Toggles via the C API

The `transcribe_run_params` structure contains two enum fields—`pnc` and `itn`—that accept one of three mode values defined in [`include/transcribe.h`](https://github.com/handy-computer/transcribe.cpp/blob/main/include/transcribe.h):

- `TRANSCRIBE_PNC_MODE_DEFAULT` / `TRANSCRIBE_ITN_MODE_DEFAULT`: Let the model decide behavior based on its internal defaults.
- `TRANSCRIBE_PNC_MODE_OFF` / `TRANSCRIBE_ITN_MODE_OFF`: Explicitly disable the feature.
- `TRANSCRIBE_PNC_MODE_ON` / `TRANSCRIBE_ITN_MODE_ON`: Explicitly enable the feature.

After populating the structure, pass it to `transcribe_run` to apply the settings during transcription.

```c
transcribe_run_params rp = {0};

/* Explicitly enable both features */
if (has_pnc) {
    rp.pnc = TRANSCRIBE_PNC_MODE_ON;
}
if (has_itn) {
    rp.itn = TRANSCRIBE_ITN_MODE_ON;
}

/* Execute transcription with specified parameters */
transcribe_output out;
transcribe_status st = transcribe_run(model, &rp, audio_data, &out);

```

## Using Toggles in the Command-Line Interface

The CLI implementation in [`examples/cli/main.cpp`](https://github.com/handy-computer/transcribe.cpp/blob/main/examples/cli/main.cpp) maps command-line flags directly to the `transcribe_run_params` fields. You can toggle these features using boolean-style flags:

- `--pnc` and `--no-pnc` control punctuation and capitalization.
- `--itn` and `--no-itn` control inverse text normalization.

When specified, the CLI translates these flags into the corresponding enum values before calling the transcription runtime.

```bash
build/bin/transcribe-cli \
    -m models/canary-1b-F32.gguf \
    --pnc \
    --no-itn \
    samples/example.wav

```

## Implementation by Model Family

Different transcription families handle these toggles according to their architecture:

- **Canary**: Implements PNC through the `<pnc>` slot in the multitask prompt, as documented in [`docs/porting/families/canary.md`](https://github.com/handy-computer/transcribe.cpp/blob/main/docs/porting/families/canary.md).
- **SenseVoice**: Uses the `use_itn` flag internally to control inverse text normalization, documented in [`docs/porting/families/sensevoice.md`](https://github.com/handy-computer/transcribe.cpp/blob/main/docs/porting/families/sensevoice.md).
- **Whisper**: Does not implement these toggles; the parameters exist in the API but are ignored during execution.
- **Fun-ASR-Nano**: Reads the toggle fields directly when initializing the inference pipeline.

## Summary

- **Check support first**: Always verify `TRANSCRIBE_FEATURE_PNC` or `TRANSCRIBE_FEATURE_ITN` using `transcribe_model_supports()` before setting corresponding parameters.
- **Use mode enums**: Set `rp.pnc` and `rp.itn` to `*_MODE_ON`, `*_MODE_OFF`, or `*_MODE_DEFAULT` in the `transcribe_run_params` structure.
- **CLI availability**: Use `--pnc`/`--no-pnc` and `--itn`/`--no-itn` flags in the command-line interface, which map to the same underlying structure fields.
- **Model-specific behavior**: Canary and SenseVoice honor these toggles, while Whisper ignores them entirely.

## Frequently Asked Questions

### What happens if I enable PNC on a model that doesn't support it?

The library will accept the parameter in `transcribe_run_params`, but the model will ignore the setting and proceed with its default behavior. While error codes `TRANSCRIBE_ERR_UNSUPPORTED_PNC` and `TRANSCRIBE_ERR_UNSUPPORTED_ITN` are defined in [`include/transcribe.h`](https://github.com/handy-computer/transcribe.cpp/blob/main/include/transcribe.h), the current implementation in [`src/transcribe.cpp`](https://github.com/handy-computer/transcribe.cpp/blob/main/src/transcribe.cpp) does not return them, so the transcription proceeds without the requested formatting.

### What is the difference between DEFAULT and ON modes?

`TRANSCRIBE_PNC_MODE_DEFAULT` and `TRANSCRIBE_ITN_MODE_DEFAULT` defer to the model's internal configuration, which may enable or disable the feature based on training. In contrast, `*_MODE_ON` explicitly forces the feature active, and `*_MODE_OFF` explicitly forces it inactive, overriding any model defaults.

### Are these toggles available for all Whisper models?

No. According to the source analysis, the Whisper family in transcribe.cpp does not implement runtime toggles for PNC or ITN. When using Whisper models, the `pnc` and `itn` fields in `transcribe_run_params` are ignored, and the output format depends entirely on the model weights and prompt engineering.

### How do I check if my specific model supports ITN?

Call `transcribe_model_supports(model, TRANSCRIBE_FEATURE_ITN)` after loading the model. This returns a boolean indicating whether the loaded architecture can process ITN instructions. This check prevents unnecessary parameter configuration on incompatible model families.