From 5e33aa2a7e13f15f5925b5046ec69f235105fea9 Mon Sep 17 00:00:00 2001 From: Jeny Sadadia Date: Tue, 10 Feb 2026 15:16:43 +0530 Subject: [PATCH] Enable timestamps for transcripted text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add `--enable-timestamps` option to `run_client.py` script to print out transcripted text with timestamps. Sample output with translation enabled: ``` [0.000 -> 7.440] And so, my fellow Americans, ask not what your country can do for you. [7.440 -> 10.300] Ask what you can do for your country. TRANSLATION to fr: [0.000 -> 7.440] Et donc, mes camarades américains, ne demandez pas ce que votre pays peut faire pour vous. [7.440 -> 10.300] Demandez ce que vous pouvez faire pour votre pays. ``` Signed-off-by: Jeny Sadadia --- run_client.py | 4 ++++ whisper_live/client.py | 48 +++++++++++++++++++++++++++++++++--------- whisper_live/utils.py | 14 +++++++----- 3 files changed, 51 insertions(+), 15 deletions(-) diff --git a/run_client.py b/run_client.py index 827ebca..ac72cde 100644 --- a/run_client.py +++ b/run_client.py @@ -47,6 +47,9 @@ if __name__ == '__main__': type=str, default='fr', help='Target language for translation, e.g., "fr" for French.') + parser.add_argument('--enable_timestamps', + action='store_true', + help='Show transcription with timestamps') args = parser.parse_args() @@ -80,5 +83,6 @@ if __name__ == '__main__': mute_audio_playback=args.mute_audio_playback, # Only used for file input, False by Default enable_translation=args.enable_translation, # Enable translation of the transcription output target_language=args.target_language, # Target language for translation, e.g., "fr + enable_timestamps=args.enable_timestamps, ) client(f) diff --git a/whisper_live/client.py b/whisper_live/client.py index c740cd1..d380a48 100644 --- a/whisper_live/client.py +++ b/whisper_live/client.py @@ -41,6 +41,7 @@ class Client: target_language="fr", translation_callback=None, translation_srt_file_path="output_translated.srt", + enable_timestamps=False, ): """ Initializes a Client instance for audio recording and streaming to a server. @@ -97,6 +98,7 @@ class Client: self.last_translated_segment = None if translate: self.task = "translate" + self.enable_timestamps = enable_timestamps self.audio_bytes = None @@ -175,17 +177,41 @@ class Client: except Exception as e: print(f"[WARN] transcription_callback raised: {e}") return - + if self.log_transcription: - original_text = [seg["text"] for seg in self.transcript[-4:]] - if self.last_segment is not None and self.last_segment["text"] not in original_text: - original_text.append(self.last_segment["text"]) - - utils.clear_screen() - utils.print_transcript(original_text) - if self.enable_translation: - print(f"\n\nTRANSLATION to {self.target_language}:") - utils.print_transcript([seg["text"] for seg in self.translated_transcript[-4:]], translated=True) + if self.enable_timestamps: + original_text_with_timestamps = [ + {"start": seg["start"], "end": seg["end"], "text": seg["text"]} + for seg in self.transcript[-4:]] + if self.last_segment is not None and not any( + data.get("text") == self.last_segment["text"] + for data in original_text_with_timestamps): + original_text_with_timestamps.append({ + "start": self.last_segment["start"], + "end": self.last_segment["end"], + "text": self.last_segment["text"] + }) + utils.clear_screen() + utils.print_transcript(original_text_with_timestamps, timestamps=True) + + if self.enable_translation: + print(f"\n\nTRANSLATION to {self.target_language}:") + utils.print_transcript([ + {"start": seg["start"], "end": seg["end"], "text": seg["text"]} + for seg in self.translated_transcript[-4:] + ], timestamps=True) + + else: + original_text = [seg["text"] for seg in self.transcript[-4:]] + if self.last_segment is not None and self.last_segment["text"] not in original_text: + original_text.append(self.last_segment["text"]) + utils.clear_screen() + utils.print_transcript(original_text) + + if self.enable_translation: + print(f"\n\nTRANSLATION to {self.target_language}:") + utils.print_transcript([seg["text"] for seg in self.translated_transcript[-4:]], translated=True) + def on_message(self, ws, message): """ @@ -790,6 +816,7 @@ class TranscriptionClient(TranscriptionTeeClient): target_language="fr", translation_callback=None, translation_srt_file_path="./output_translated.srt", + enable_timestamps=False, ): self.client = Client( host, @@ -810,6 +837,7 @@ class TranscriptionClient(TranscriptionTeeClient): target_language=target_language, translation_callback=translation_callback, translation_srt_file_path=translation_srt_file_path, + enable_timestamps=enable_timestamps, ) if save_output_recording and not output_recording_filename.endswith(".wav"): diff --git a/whisper_live/utils.py b/whisper_live/utils.py index a846d32..43fefae 100644 --- a/whisper_live/utils.py +++ b/whisper_live/utils.py @@ -11,12 +11,16 @@ def clear_screen(): os.system("cls" if os.name == "nt" else "clear") -def print_transcript(text, translated=False): +def print_transcript(text, translated=False, timestamps=False): """Prints formatted transcript text.""" - wrapper = textwrap.TextWrapper(width=60) - text=" ".join(text) if translated else "".join(text) - for line in wrapper.wrap(text=text): - print(line) + if timestamps: + for t in text: + print(f'[{t["start"]} -> {t["end"]}] {t["text"]}') + else: + wrapper = textwrap.TextWrapper(width=60) + text=" ".join(text) if translated else "".join(text) + for line in wrapper.wrap(text=text): + print(line) def format_time(s):