class_docstr: Speech2Text class
  
  Examples:
      >>> import soundfile
      >>> speech2text = k2Speech2Text("uasr_config.yml", "uasr.pth")
      >>> audio, rate = soundfile.read("speech.wav")
      >>> speech = np.expand_dims(audio, 0) # shape: [batch_size, speech_length]
      >>> speech_lengths = np.array([audio.shape[0]]) # shape: [batch_size]
      >>> batch = {"speech": speech, "speech_lengths", speech_lengths}
      >>> speech2text(batch)
      [(text, token, token_int, score), ...]
docstr: Inference
  
  Args:
      batch: Input speech data and corresponding lengths
  Returns:
      text, token, token_int, hyp
docstr_tok: ["Inference","Args",":","batch",":","Input","speech","data","and","corresponding","lengths","Returns",":","text",",","token",",","token_int",",","hyp"]
code: def __call__(
      self, speech: Union[torch.Tensor, np.ndarray]
  ) -> List[Tuple[Optional[str], List[str], List[int], float]]:
      """Inference
  
      Args:
          batch: Input speech data and corresponding lengths
      Returns:
          text, token, token_int, hyp
  
      """
      assert check_argument_types()
  
      if isinstance(speech, np.ndarray):
          speech = torch.tensor(speech)
  
      # data: (Nsamples,) -> (1, Nsamples)
      speech = speech.unsqueeze(0).to(getattr(torch, self.dtype))
      # lengths: (1,)
      lengths = speech.new_full(
          [1], dtype=torch.long, fill_value=speech.size(1)
      )
      batch = {"speech": speech, "speech_lengths": lengths}
  
      # a. To device
      batch = to_device(batch, device=self.device)
  
      # b. Forward Encoder
      # enc: [N, T, C]
      generated_sample, _ = self.uasr_model.inference(**batch)
  
      # nnet_output: [N, T, C]
      logp_encoder_output = torch.nn.functional.log_softmax(
          generated_sample, dim=-1
      )
  
      # It maybe useful to tune blank_bias.
      # The valid range of blank_bias is [-inf, 0]
      #        logp_encoder_output[:, :, 4] += 0
  
      batch_size, time_length, _ = generated_sample.shape
      assert batch_size == 1
      sequence_idx = 0
      start_frame = 0
      num_frames = time_length
      supervision_segments = torch.Tensor(
          [[sequence_idx, start_frame, num_frames]]
      )
      supervision_segments = supervision_segments.to(torch.int32)
  
      # An introduction to DenseFsaVec:
      # https://k2-fsa.github.io/k2/core_concepts/index.html#dense-fsa-vector
      # It could be viewed as a fsa-type lopg_encoder_output,
      # whose weight on the arcs are initialized with logp_encoder_output.
      # The goal of converting tensor-type to fsa-type is using
      # fsa related functions in k2. e.g. k2.intersect_dense_pruned below
  
      # The term "intersect" is similar to "compose" in k2.
      # The differences is are:
      # for "compose" functions, the composition involves
      # mathcing output label of a.fsa and input label of b.fsa
      # while for "intersect" functions, the composition involves
      # matching input label of a.fsa and input label of b.fsa
      # Actually, in compose functions, b.fsa is inverted and then
      # a.fsa and inv_b.fsa are intersected together.
      # For difference between compose and interset:
      # https://github.com/k2-fsa/k2/blob/master/k2/python/k2/fsa_algo.py#L308
      # For definition of k2.intersect_dense_pruned:
      # https://github.com/k2-fsa/k2/blob/master/k2/python/k2/autograd.py#L648
  
      lattices = get_lattice(
          nnet_output=logp_encoder_output,
          decoding_graph=self.decoding_graph,
          supervision_segments=supervision_segments,
          search_beam=self.search_beam_size,
          output_beam=self.output_beam_size,
          min_active_states=self.min_active_states,
          max_active_states=self.max_active_states,
      )
  
      # lattices.scores is the sum of decode_graph.scores(a.k.a. lm weight) and
      # dense_fsa_vec.scores(a.k.a. am weight) on related arcs.
      # For ctc decoding graph, lattices.scores only store am weight
      # since the decoder_graph only define the ctc topology and
      # has no lm weight on its arcs.
      # While for 3-gram decoding, whose graph is converted from language models,
      # lattice.scores contains both am weights and lm weights
      #
      # It maybe useful to tune lattice.scores
      # The valid range of lattice_weight is [0, inf)
      # The lattice_weight will affect the search of k2.random_paths
      lattices.scores *= self.lattice_weight
  
      results = []
      # TODO(Dongji): add nbest_rescoring
      if self.use_nbest_rescoring:
          raise ValueError("Currently nbest rescoring is not supported")
      else:
          best_paths = one_best_decoding(
              lattices, use_double_scores=True
          )
          scores = best_paths.get_tot_scores(
              use_double_scores=True, log_semiring=False
          ).tolist()
          hyps = get_texts(best_paths)
  
      assert len(scores) == len(hyps)
  
      for token_int, score in zip(hyps, scores):
          # For decoding methods nbest_rescoring and ctc_decoding
          # hyps stores token_index, which is lattice.labels.
  
          # convert token_id to text with self.tokenizer
          token = self.converter.ids2tokens(token_int)
          assert self.tokenizer is not None
          text = self.tokenizer.tokens2text(token)
          results.append((text, token, token_int, score))
  
      assert check_return_type(results)
      return results
  
imports: import argparse
  import datetime
  import logging
  import sys
  from pathlib import Path
  from typing import Any, List, Optional, Sequence, Tuple, Union
  import numpy
  import torch
  import yaml
  from typeguard import check_argument_types, check_return_type
  from espnet2.fileio.datadir_writer import DatadirWriter
  from espnet2.tasks.lm import LMTask
  from espnet2.tasks.uasr import UASRTask
  from espnet2.text.build_tokenizer import build_tokenizer
  from espnet2.text.token_id_converter import TokenIDConverter
  from espnet2.torch_utils.device_funcs import to_device
  from espnet2.torch_utils.set_all_random_seed import set_all_random_seed
  from espnet2.utils import config_argparse
  from espnet2.utils.types import str2bool, str2triple_str, str_or_none
  from espnet.nets.pytorch_backend.transformer.subsampling import TooShortUttError
  from espnet.utils.cli_utils import get_commandline_args
label_desc: Use image node_id 2 for calling the k2Speech2Text obj's underlying member method code with example usage: obj.__call__(speech) and returns: results