Automatic Speech Recognition
Transformers
Safetensors
English
asr_model
asr
speech-recognition
speech-to-text
audio
speech-llm
word-timestamps
speaker-diarization
qwen
granite-speech
lora
custom_code
Eval Results (legacy)
Instructions to use mazesmazes/tiny-audio with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use mazesmazes/tiny-audio with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("automatic-speech-recognition", model="mazesmazes/tiny-audio", trust_remote_code=True)# pip install -U transformers accelerate # Load model directly from transformers import AutoModelForSpeechSeq2Seq model = AutoModelForSpeechSeq2Seq.from_pretrained("mazesmazes/tiny-audio", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
Download handler.py from mazesmazes/tiny-audio: direct link, hf CLI and curl.
- Browser
- Download file 4.6 kB
-
https://huggingface.co/mazesmazes/tiny-audio/resolve/main/handler.py
- Command line
-
hf download hf://mazesmazes/tiny-audio/handler.py
-
curl -L -o handler.py https://huggingface.co/mazesmazes/tiny-audio/resolve/main/handler.py
4.6 kB
| """Custom inference handler for HuggingFace Inference Endpoints.""" | |
| import base64 | |
| import binascii | |
| import os | |
| from pathlib import Path | |
| from typing import TYPE_CHECKING, Any | |
| if TYPE_CHECKING: | |
| from .alignment import QwenForcedAligner | |
| from .asr_modeling import ASRModel | |
| from .asr_pipeline import ASRPipeline | |
| from .diarization import NemotronDiarizer | |
| from .diarization import get_device as _best_device | |
| else: | |
| try: | |
| # For remote execution, imports are relative | |
| from .alignment import QwenForcedAligner | |
| from .asr_modeling import ASRModel | |
| from .asr_pipeline import ASRPipeline | |
| from .diarization import NemotronDiarizer | |
| from .diarization import get_device as _best_device | |
| except ImportError: | |
| # For local execution, imports are not relative | |
| from alignment import QwenForcedAligner | |
| from asr_modeling import ASRModel | |
| from asr_pipeline import ASRPipeline | |
| from diarization import NemotronDiarizer | |
| from diarization import get_device as _best_device | |
| def decode_inputs(inputs: Any) -> Any: | |
| """A JSON request's base64 audio as bytes; paths, raw bytes and arrays unchanged. | |
| The toolkit hands `inputs` over as raw bytes for an `audio/*` body, but a | |
| JSON body can only carry audio as a base64 string, which the pipeline | |
| would otherwise read as a file path. | |
| """ | |
| if not isinstance(inputs, str) or Path(inputs).exists(): | |
| return inputs | |
| try: | |
| return base64.b64decode(inputs, validate=True) | |
| except (binascii.Error, ValueError): | |
| return inputs | |
| class EndpointHandler: | |
| """HuggingFace Inference Endpoints handler for ASR model. | |
| Handles model loading, warmup, and inference requests for deployment | |
| on HuggingFace Inference Endpoints or similar services. | |
| """ | |
| def __init__(self, path: str = ""): | |
| """Initialize the endpoint handler. | |
| Args: | |
| path: Path to model directory or HuggingFace model ID | |
| """ | |
| os.environ.setdefault("PYTORCH_CUDA_ALLOC_CONF", "expandable_segments:True") | |
| # `ASRModel.from_pretrained` constructs its own submodules and forwards | |
| # **kwargs to `ASRModel.__init__`, which discards them -- no loader | |
| # reads `device_map`, `torch_dtype` or `low_cpu_mem_usage`, and it sets | |
| # `_is_loading_from_pretrained` precisely to keep `device_map="auto"` | |
| # out of the sub-model loaders. Passing them here did nothing, so the | |
| # model stayed on CPU and a GPU Inference Endpoint silently decoded on | |
| # CPU. Place it explicitly instead. dtype comes from | |
| # `config.model_dtype` and the attention backend from | |
| # `config.attn_implementation`, which already downgrades FA2 when | |
| # flash_attn is missing. | |
| self.model = ASRModel.from_pretrained(path) | |
| self.device = _best_device() | |
| # PreTrainedModel.to is functools.wraps'd, which pyright cannot bind as a method. | |
| self.model.to(self.device) # pyright: ignore[reportArgumentType] | |
| self.model.eval() | |
| self.pipe = ASRPipeline( | |
| model=self.model, | |
| feature_extractor=self.model.feature_extractor, | |
| tokenizer=self.model.tokenizer, | |
| device=self.device, | |
| ) | |
| # Load the forced aligner (return_timestamps) and Nemotron diarizer | |
| # (return_speakers) at boot, as the Spaces demo does, so the first | |
| # request that asks for them doesn't pay the download and load. | |
| QwenForcedAligner.get_instance() | |
| NemotronDiarizer.get_instance() | |
| def __call__(self, data: dict[str, Any]) -> dict[str, Any] | list[dict[str, Any]]: | |
| """Process an inference request. | |
| Args: | |
| data: Request data containing 'inputs' (audio path, bytes or base64 | |
| string) and optional 'parameters' for the pipeline, e.g. | |
| `return_timestamps`, `return_speakers`, `num_speakers`, | |
| `max_speakers` -- the same options as the Spaces demo | |
| Returns: | |
| Transcription result with 'text' key; 'words' with timestamps, plus | |
| speaker labels and 'speaker_segments' when diarizing | |
| """ | |
| inputs = data.get("inputs") | |
| if inputs is None: | |
| msg = "Missing 'inputs' in request data" | |
| raise ValueError(msg) | |
| # Pass through any parameters from request, let model config provide defaults | |
| params = data.get("parameters", {}) | |
| result: dict[str, Any] | list[dict[str, Any]] = self.pipe(decode_inputs(inputs), **params) | |
| return result | |