def refine(
            self,
            audio: Union[str, np.ndarray, torch.Tensor, bytes],
            result: WhisperResult,
            inplace: bool = True,
            encode: Optional[Callable] = None,
            **options
    ) -> WhisperResult:
        """

        Parameters
        ----------
        audio : str or numpy.ndarray or torch.Tensor or bytes
            Path/URL to the audio file, the audio waveform, or bytes of audio file.
            If audio is :class:`numpy.ndarray` or :class:`torch.Tensor`, the audio must be already at sampled to 16kHz.
        result : stable_whisper.result.WhisperResult
            All timestamps, words, probabilities, and other data from the transcription of ``audio``.
        inplace : bool, default True
            Whether to update ``result`` with new timestamps if it is an instance of
            :class:`stable_whisper.result.WhisperResult`.
        encode : Callable, optional
            Function for tokenizing text. Only needed if ``result`` is missing tokens.

        Returns
        -------
        stable_whisper.result.WhisperResult
            All timestamps, words, probabilities, and other data from the alignment of ``audio``.
            Same object as ``result`` if ``inplace=True`` (default) and ``result`` is a ``WhisperResult``..

        """

        if result:
            if not result.has_words:
                raise RuntimeError(f'cannot refine result with missing word-timestamps')
            elif not all(word.tokens for word in result.all_words()):
                if encode is None:
                    raise RuntimeError(f'result must have tokens or provide tokenization function to ``encode``')
                for word in result.all_words():
                    word.tokens = encode(word.word)

        if not inplace:
            result = copy.deepcopy(result)

        self._load_audio(audio)
        for k in list(options.keys()):
            if hasattr(self, k):
                setattr(self, k, options.pop(k))
        self.options.update(options)

        with tqdm(
                total=round(self._audio.size(-1) / self.sample_rate, 2), unit='sec',
                disable=self.options.progress.verbose is not False,
                desc='Refine'
        ) as self._tqdm_pbar:

            self._pbar_step = self._tqdm_pbar.total / len(self.steps)
            for step_count, step in enumerate(self.steps, 1):
                self._step_count = step_count
                self._prev_ts = 0
                self._refine(result, step)
                self.update_pbar(self._tqdm_pbar.total)
            self._tqdm_pbar.update(self._tqdm_pbar.total - self._tqdm_pbar.n)

        result.reassign_ids()

        return result


        Parameters
        ----------
        audio : str or numpy.ndarray or torch.Tensor or bytes
            Path/URL to the audio file, the audio waveform, or bytes of audio file.
            If audio is :class:`numpy.ndarray` or :class:`torch.Tensor`, the audio must be already at sampled to 16kHz.
        result : stable_whisper.result.WhisperResult
            All timestamps, words, probabilities, and other data from the transcription of ``audio``.
        inplace : bool, default True
            Whether to update ``result`` with new timestamps if it is an instance of
            :class:`stable_whisper.result.WhisperResult`.
        encode : Callable, optional
            Function for tokenizing text. Only needed if ``result`` is missing tokens.

        Returns
        -------
        stable_whisper.result.WhisperResult
            All timestamps, words, probabilities, and other data from the alignment of ``audio``.
            Same object as ``result`` if ``inplace=True`` (default) and ``result`` is a ``WhisperResult``..

        
stable_whisper/non_whisper/refinement.py