diff --git a/README.md b/README.md index 49ed1bb..7861b82 100644 --- a/README.md +++ b/README.md @@ -45,12 +45,16 @@ The server supports 3 backends `faster_whisper`, `tensorrt` and `openvino`. If r - [Faster Whisper](https://github.com/SYSTRAN/faster-whisper) backend ```bash python3 run_server.py --port 9090 \ - --backend faster_whisper + --backend faster_whisper \ + --max_clients 4 \ + --max_connection_time 600 # running with custom model and cache_dir to save auto-converted ctranslate2 models python3 run_server.py --port 9090 \ --backend faster_whisper \ - -fw "/path/to/custom/faster/whisper/model" + --max_clients 4 \ + --max_connection_time 600 \ + -fw "/path/to/custom/faster/whisper/model" \ -c ~/.cache/whisper-live/ ``` @@ -59,15 +63,20 @@ python3 run_server.py --port 9090 \ # Run English only model python3 run_server.py -p 9090 \ -b tensorrt \ - -trt /home/TensorRT-LLM/examples/whisper/whisper_small_en + -trt /home/TensorRT-LLM/examples/whisper/whisper_small_en \ + --max_clients 4 \ + --max_connection_time 600 # Run Multilingual model python3 run_server.py -p 9090 \ -b tensorrt \ -trt /home/TensorRT-LLM/examples/whisper/whisper_small \ - -m + -m \ + --max_clients 4 \ + --max_connection_time 600 ``` - +- Use `--max_clients` option to restrict the number of clients the server should allow. Defaults to 4. +- Use `--max_connection_time` options to limit connection time for a client in seconds. Defaults to 600. - WhisperLive now supports the [OpenVINO](https://github.com/openvinotoolkit/openvino) backend for efficient inference on Intel CPUs, iGPU and dGPUs. Currently, we tested the models uploaded to [huggingface by OpenVINO](https://huggingface.co/OpenVINO?search_models=whisper). - > **Docker Recommended:** Running WhisperLive with OpenVINO inside Docker automatically enables GPU support (iGPU/dGPU) without requiring additional host setup. - > **Native (non-Docker) Use:** If you prefer running outside Docker, ensure the Intel drivers and OpenVINO runtime are installed and properly configured on your system. Refer to the documentation for [installing OpenVINO](https://docs.openvino.ai/2025/get-started/install-openvino.html?PACKAGE=OPENVINO_BASE&VERSION=v_2025_0_0&OP_SYSTEM=LINUX&DISTRIBUTION=PIP#). @@ -101,8 +110,6 @@ If you don't want this, set `--no_single_model`. - `use_vad`: Whether to use `Voice Activity Detection` on the server. - `save_output_recording`: Set to True to save the microphone input as a `.wav` file during live transcription. This option is helpful for recording sessions for later playback or analysis. Defaults to `False`. - `output_recording_filename`: Specifies the `.wav` file path where the microphone input will be saved if `save_output_recording` is set to `True`. - - `max_clients`: Specifies the maximum number of clients the server should allow. Defaults to 4. - - `max_connection_time`: Maximum connection time for each client in seconds. Defaults to 600. - `mute_audio_playback`: Whether to mute audio playback when transcribing an audio file. Defaults to False. ```python @@ -116,8 +123,6 @@ client = TranscriptionClient( use_vad=False, save_output_recording=True, # Only used for microphone input, False by Default output_recording_filename="./output_recording.wav", # Only used for microphone input - max_clients=4, - max_connection_time=600, mute_audio_playback=False, # Only used for file input, False by Default ) ``` diff --git a/run_client.py b/run_client.py index fde26e6..33035fb 100644 --- a/run_client.py +++ b/run_client.py @@ -3,55 +3,72 @@ import sys from whisper_live.client import TranscriptionClient import argparse + if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument('--port', '-p', - type=int, - default=9090, - help="Websocket port to run the server on.") - parser.add_argument('--server', '-s', - type=str, - default='localhost', - help='hostname or ip address of server') - parser.add_argument('--files', '-f', - type=str, - nargs='+', - help='hostname or ip address of server') - parser.add_argument('--output_file', '-o', - type=str, - default='./output_recording.wav', - help='hostname or ip address of server') - args = parser.parse_args() + parser = argparse.ArgumentParser() + parser.add_argument('--port', '-p', + type=int, + default=9090, + help="Websocket port to run the server on.") + parser.add_argument('--server', '-s', + type=str, + default='localhost', + help='hostname or ip address of server') + parser.add_argument('--files', '-f', + type=str, + nargs='+', + help='Files to transcribe, separated by spaces. ' + 'If not provided, will use microphone input.') + parser.add_argument('--output_file', '-o', + type=str, + default='./output_recording.wav', + help='output recording filename, only used for microphone input.') + parser.add_argument('--model', '-m', + type=str, + default='small', + help='Model to use for transcription, e.g., "tiny, small.en, large-v3".') + parser.add_argument('--lang', '-l', + type=str, + default='en', + help='Language code for transcription, e.g., "en" for English.') + parser.add_argument('--translate', '-t', + action='store_true', + help='Enable translation of the transcription output.') + parser.add_argument('--mute_audio_playback', '-a', + action='store_true', + help='Mute audio playback during transcription.') + parser.add_argument('--save_output_recording', '-r', + action='store_true', + help='Save the output recording, only used for microphone input.') + args = parser.parse_args() - # Validate audio files - valid_files = [] - for file_path in args.files: - path = Path(file_path) - if path.exists() and path.is_file(): - valid_files.append(str(path)) - else: - print(f"Warning: File not found: {file_path}") + # Validate audio files + valid_files = [] + for file_path in args.files: + path = Path(file_path) + if path.exists() and path.is_file(): + valid_files.append(str(path)) + else: + print(f"Warning: File not found: {file_path}") - if not valid_files: - print("Error: No valid audio files found!") - sys.exit(1) + if not valid_files: + print("Error: No valid audio files found!") + sys.exit(1) - print(f"Found {len(valid_files)} audio file(s) to stream:") - for file_path in valid_files: - print(f" - {file_path}") + print(f"Found {len(valid_files)} audio file(s) to stream:") + for file_path in valid_files: + print(f" - {file_path}") - for f in valid_files: - client = TranscriptionClient( - args.server, - args.port, - lang="en", - translate=False, - model="large-v3", # also support hf_model => `Systran/faster-whisper-small` - use_vad=False, - save_output_recording=False, # Only used for microphone input, False by Default - output_recording_filename=args.output_file, # Only used for microphone input - max_clients=4, - max_connection_time=600, - mute_audio_playback=True, # Only used for file input, False by Default - ) - client(f) + for f in valid_files: + client = TranscriptionClient( + args.server, + args.port, + lang=args.lang, + translate=args.translate, + model=args.model, # also support hf_model => `Systran/faster-whisper-small` + use_vad=True, + save_output_recording=args.save_output_recording, # Only used for microphone input, False by Default + output_recording_filename=args.output_file, # Only used for microphone input + mute_audio_playback=args.mute_audio_playback, # Only used for file input, False by Default + ) + client(f) diff --git a/run_server.py b/run_server.py index 980b639..ed61bc8 100644 --- a/run_server.py +++ b/run_server.py @@ -31,6 +31,14 @@ if __name__ == "__main__": parser.add_argument('--no_single_model', '-nsm', action='store_true', help='Set this if every connection should instantiate its own model. Only relevant for custom model, passed using -trt or -fw.') + parser.add_argument('--max_clients', + type=int, + default=4, + help='Maximum clients supported by the server.') + parser.add_argument('--max_connection_time', + type=int, + default=300, + help='Path to cache the converted ctranslate2 models.') parser.add_argument('--cache_path', '-c', type=str, default="~/.cache/whisper-live/", @@ -55,5 +63,7 @@ if __name__ == "__main__": trt_multilingual=args.trt_multilingual, trt_py_session=args.trt_py_session, single_model=not args.no_single_model, + max_clients=args.max_clients, + max_connection_time=args.max_connection_time, cache_path=args.cache_path ) diff --git a/whisper_live/client.py b/whisper_live/client.py index 197afb9..ada8322 100644 --- a/whisper_live/client.py +++ b/whisper_live/client.py @@ -32,8 +32,6 @@ class Client: use_vad=True, use_wss=False, log_transcription=True, - max_clients=4, - max_connection_time=600, send_last_n_segments=10, no_speech_thresh=0.45, clip_audio=False, @@ -56,8 +54,6 @@ class Client: srt_file_path (str, optional): The file path to save the output SRT file. Default is "output.srt". use_vad (bool, optional): Whether to enable voice activity detection. Default is True. log_transcription (bool, optional): Whether to log transcription output to the console. Default is True. - max_clients (int, optional): Maximum number of client connections allowed. Default is 4. - max_connection_time (int, optional): Maximum allowed connection time in seconds. Default is 600. send_last_n_segments (int, optional): Number of most recent segments to send to the client. Defaults to 10. no_speech_thresh (float, optional): Segments with no speech probability above this threshold will be discarded. Defaults to 0.45. clip_audio (bool, optional): Whether to clip audio with no valid segments. Defaults to False. @@ -79,8 +75,6 @@ class Client: self.last_segment = None self.last_received_segment = None self.log_transcription = log_transcription - self.max_clients = max_clients - self.max_connection_time = max_connection_time self.send_last_n_segments = send_last_n_segments self.no_speech_thresh = no_speech_thresh self.clip_audio = clip_audio @@ -236,8 +230,6 @@ class Client: "task": self.task, "model": self.model, "use_vad": self.use_vad, - "max_clients": self.max_clients, - "max_connection_time": self.max_connection_time, "send_last_n_segments": self.send_last_n_segments, "no_speech_thresh": self.no_speech_thresh, "clip_audio": self.clip_audio, @@ -714,8 +706,6 @@ class TranscriptionClient(TranscriptionTeeClient): output_recording_filename (str, optional): Path to save the output recording WAV file. Default is "./output_recording.wav". output_transcription_path (str, optional): File path to save the output transcription (SRT file). Default is "./output.srt". log_transcription (bool, optional): Whether to log transcription output to the console. Default is True. - max_clients (int, optional): Maximum number of client connections allowed. Default is 4. - max_connection_time (int, optional): Maximum allowed connection time in seconds. Default is 600. mute_audio_playback (bool, optional): If True, mutes audio playback during file playback. Default is False. send_last_n_segments (int, optional): Number of most recent segments to send to the client. Defaults to 10. no_speech_thresh (float, optional): Segments with no speech probability above this threshold will be discarded. Defaults to 0.45. @@ -746,8 +736,6 @@ class TranscriptionClient(TranscriptionTeeClient): output_recording_filename="./output_recording.wav", output_transcription_path="./output.srt", log_transcription=True, - max_clients=4, - max_connection_time=600, mute_audio_playback=False, send_last_n_segments=10, no_speech_thresh=0.45, @@ -765,8 +753,6 @@ class TranscriptionClient(TranscriptionTeeClient): use_vad=use_vad, use_wss=use_wss, log_transcription=log_transcription, - max_clients=max_clients, - max_connection_time=max_connection_time, send_last_n_segments=send_last_n_segments, no_speech_thresh=no_speech_thresh, clip_audio=clip_audio, diff --git a/whisper_live/server.py b/whisper_live/server.py index edb5d35..f58eaec 100644 --- a/whisper_live/server.py +++ b/whisper_live/server.py @@ -269,11 +269,6 @@ class TranscriptionServer: options = websocket.recv() options = json.loads(options) - if self.client_manager is None: - max_clients = options.get('max_clients', 4) - max_connection_time = options.get('max_connection_time', 600) - self.client_manager = ClientManager(max_clients, max_connection_time) - self.use_vad = options.get('use_vad') if self.client_manager.is_server_full(websocket, options): websocket.close() @@ -372,6 +367,8 @@ class TranscriptionServer: trt_multilingual=False, trt_py_session=False, single_model=False, + max_clients=4, + max_connection_time=600, cache_path="~/.cache/whisper-live/"): """ Run the transcription server. @@ -381,6 +378,9 @@ class TranscriptionServer: port (int): The port number to bind the server. """ self.cache_path = cache_path + self.client_manager = ClientManager(max_clients, max_connection_time) + if faster_whisper_custom_model_path is not None and not os.path.exists(faster_whisper_custom_model_path): + raise ValueError(f"Custom faster_whisper model '{faster_whisper_custom_model_path}' is not a valid path.") if whisper_tensorrt_path is not None and not os.path.exists(whisper_tensorrt_path): raise ValueError(f"TensorRT model '{whisper_tensorrt_path}' is not a valid path.") if single_model: