code: def _detect_speech(self, audio: np.array) -> np.array:
      if audio.shape[0] < self.trim_win_length:
          return np.array([])
  
      # [num_frames, win_length]
      audio_frames = librosa.util.frame(
          audio,
          frame_length=self.trim_win_length,
          hop_length=self.trim_hop_length,
      ).transpose()
      audio_frame_lengths = audio_frames.shape[0] * [
          self.trim_win_length
      ]
  
      # [num_frames, win_length]
      audio_signal = torch.tensor(
          audio_frames, dtype=torch.float32, device=self.device
      )
      # [1]
      audio_signal_len = torch.tensor(
          audio_frame_lengths, dtype=torch.int32, device=self.device
      )
      # VAD outputs 2 values for each audio frame with logits indicating the likelihood that
      # each frame is non-speech or speech, respectively.
      # [num_frames, 2]
      log_probs = self.vad_model(
          input_signal=audio_signal,
          input_signal_length=audio_signal_len,
      )
      probs = torch.softmax(log_probs, dim=-1)
      probs = probs.detach().cpu().numpy()
      # [num_frames]
      speech_probs = probs[:, 1]
      speech_frames = speech_probs >= self.vad_threshold
  
      return speech_frames
  
imports: from abc import ABC, abstractmethod
  from typing import Tuple
  import librosa
  import numpy
  import torch
  from nemo.collections.asr.models import EncDecClassificationModel
  from nemo.collections.tts.parts.utils.tts_dataset_utils import normalize_volume
  from nemo.utils import logging
label_desc: Use image node_id 2 for calling the VadAudioTrimmer obj's underlying member method code with example usage: obj._detect_speech(audio) and returns: speech_frames, np