[Fix] Controller: Handle VRAM overflow errors during translation and transcription processes.

This commit is contained in:
misyaguziya
2025-06-02 15:07:33 +09:00
parent 7b42387a19
commit dfc90508d1
4 changed files with 240 additions and 54 deletions

View File

@@ -259,6 +259,7 @@ class Controller:
elif config.ENABLE_TRANSLATION is False: elif config.ENABLE_TRANSLATION is False:
pass pass
else: else:
try:
translation, success = model.getInputTranslate(message, source_language=language) translation, success = model.getInputTranslate(message, source_language=language)
if all(success) is not True: if all(success) is not True:
self.changeToCTranslate2Process() self.changeToCTranslate2Process()
@@ -270,6 +271,32 @@ class Controller:
"data": None "data": None
}, },
) )
except Exception as e:
# VRAM不足エラーの検出
is_vram_error, error_message = model.detectVRAMError(e)
if is_vram_error:
self.run(
400,
self.run_mapping["error_translation_mic_vram_overflow"],
{
"message":"VRAM out of memory during translation of mic",
"data": error_message
},
)
# 翻訳機能をOFFにする
self.setDisableTranslation()
self.run(
400,
self.run_mapping["enable_translation"],
{
"message":"Translation disabled due to VRAM overflow",
"data": False
},
)
return
else:
# その他のエラーは通常通り処理
raise
if config.CONVERT_MESSAGE_TO_ROMAJI is True or config.CONVERT_MESSAGE_TO_HIRAGANA is True: if config.CONVERT_MESSAGE_TO_ROMAJI is True or config.CONVERT_MESSAGE_TO_HIRAGANA is True:
if config.SELECTED_TARGET_LANGUAGES[config.SELECTED_TAB_NO]["1"]["language"] == "Japanese": if config.SELECTED_TARGET_LANGUAGES[config.SELECTED_TAB_NO]["1"]["language"] == "Japanese":
@@ -346,6 +373,7 @@ class Controller:
elif config.ENABLE_TRANSLATION is False: elif config.ENABLE_TRANSLATION is False:
pass pass
else: else:
try:
translation, success = model.getOutputTranslate(message, source_language=language) translation, success = model.getOutputTranslate(message, source_language=language)
if all(success) is not True: if all(success) is not True:
self.changeToCTranslate2Process() self.changeToCTranslate2Process()
@@ -357,6 +385,32 @@ class Controller:
"data": None "data": None
}, },
) )
except Exception as e:
# VRAM不足エラーの検出
is_vram_error, error_message = model.detectVRAMError(e)
if is_vram_error:
self.run(
400,
self.run_mapping["error_translation_speaker_vram_overflow"],
{
"message":"VRAM out of memory during translation of speaker",
"data": error_message
},
)
# 翻訳機能をOFFにする
self.setDisableTranslation()
self.run(
400,
self.run_mapping["enable_translation"],
{
"message":"Translation disabled due to VRAM overflow",
"data": False
},
)
return
else:
# その他のエラーは通常通り処理
raise
if config.CONVERT_MESSAGE_TO_ROMAJI is True or config.CONVERT_MESSAGE_TO_HIRAGANA is True: if config.CONVERT_MESSAGE_TO_ROMAJI is True or config.CONVERT_MESSAGE_TO_HIRAGANA is True:
if config.SELECTED_TARGET_LANGUAGES[config.SELECTED_TAB_NO]["1"]["language"] == "Japanese": if config.SELECTED_TARGET_LANGUAGES[config.SELECTED_TAB_NO]["1"]["language"] == "Japanese":
@@ -417,6 +471,7 @@ class Controller:
if config.ENABLE_TRANSLATION is False: if config.ENABLE_TRANSLATION is False:
pass pass
else: else:
try:
if config.USE_EXCLUDE_WORDS is True: if config.USE_EXCLUDE_WORDS is True:
replacement_message, replacement_dict = self.replaceExclamationsWithRandom(message) replacement_message, replacement_dict = self.replaceExclamationsWithRandom(message)
translation, success = model.getInputTranslate(replacement_message) translation, success = model.getInputTranslate(replacement_message)
@@ -437,6 +492,41 @@ class Controller:
"data": None "data": None
}, },
) )
except Exception as e:
# VRAM不足エラーの検出
is_vram_error, error_message = model.detectVRAMError(e)
if is_vram_error:
self.run(
400,
self.run_mapping["error_translation_chat_vram_overflow"],
{
"message":"VRAM out of memory during translation of chat",
"data": error_message
},
)
# 翻訳機能をOFFにする
self.setDisableTranslation()
self.run(
400,
self.run_mapping["enable_translation"],
{
"message":"Translation disabled due to VRAM overflow",
"data": False
},
)
# エラー時は翻訳なしで返す
return {"status":200,
"result":
{
"id":id,
"message":message,
"translation":[],
"transliteration":[],
},
}
else:
# その他のエラーは通常通り処理
raise
if config.CONVERT_MESSAGE_TO_ROMAJI is True or config.CONVERT_MESSAGE_TO_HIRAGANA is True: if config.CONVERT_MESSAGE_TO_ROMAJI is True or config.CONVERT_MESSAGE_TO_HIRAGANA is True:
if config.SELECTED_TARGET_LANGUAGES[config.SELECTED_TAB_NO]["1"]["language"] == "Japanese": if config.SELECTED_TARGET_LANGUAGES[config.SELECTED_TAB_NO]["1"]["language"] == "Japanese":
@@ -514,8 +604,21 @@ class Controller:
@staticmethod @staticmethod
def setSelectedTranslationComputeDevice(device:str, *args, **kwargs) -> dict: def setSelectedTranslationComputeDevice(device:str, *args, **kwargs) -> dict:
printLog("setSelectedTranslationComputeDevice", device) printLog("setSelectedTranslationComputeDevice", device)
pre_device = config.SELECTED_TRANSLATION_COMPUTE_DEVICE
config.SELECTED_TRANSLATION_COMPUTE_DEVICE = device config.SELECTED_TRANSLATION_COMPUTE_DEVICE = device
try:
model.changeTranslatorCTranslate2Model() model.changeTranslatorCTranslate2Model()
except Exception as e:
# VRAM不足エラーの検出デバイス切り替え時
is_vram_error, error_message = model.detectVRAMError(e)
if is_vram_error:
# 前のデバイス設定に戻す
printLog("VRAM error detected, reverting device setting")
config.SELECTED_TRANSLATION_COMPUTE_DEVICE = pre_device
model.changeTranslatorCTranslate2Model()
else:
# その他のエラーは通常通り処理
errorLogging()
return {"status":200,"result":config.SELECTED_TRANSLATION_COMPUTE_DEVICE} return {"status":200,"result":config.SELECTED_TRANSLATION_COMPUTE_DEVICE}
@staticmethod @staticmethod
@@ -1628,7 +1731,34 @@ class Controller:
while self.device_access_status is False: while self.device_access_status is False:
sleep(1) sleep(1)
self.device_access_status = False self.device_access_status = False
try:
model.startMicTranscript(self.micMessage) model.startMicTranscript(self.micMessage)
except Exception as e:
# VRAM不足エラーの検出
is_vram_error, error_message = model.detectVRAMError(e)
if is_vram_error:
self.run(
400,
self.run_mapping["error_transcription_mic_vram_overflow"],
{
"message":"VRAM out of memory during mic transcription",
"data": error_message
},
)
# ここでマイクの音声認識を停止
self.stopTranscriptionSendMessage()
self.run(
400,
self.run_mapping["enable_transcription_send"],
{
"message":"Transcription send disabled due to VRAM overflow",
"data": False
},
)
else:
# その他のエラーは通常通り処理
errorLogging()
finally:
self.device_access_status = True self.device_access_status = True
@staticmethod @staticmethod
@@ -1650,7 +1780,34 @@ class Controller:
while self.device_access_status is False: while self.device_access_status is False:
sleep(1) sleep(1)
self.device_access_status = False self.device_access_status = False
try:
model.startSpeakerTranscript(self.speakerMessage) model.startSpeakerTranscript(self.speakerMessage)
except Exception as e:
# VRAM不足エラーの検出
is_vram_error, error_message = model.detectVRAMError(e)
if is_vram_error:
self.run(
400,
self.run_mapping["error_transcription_speaker_vram_overflow"],
{
"message":"VRAM out of memory during speaker transcription",
"data": error_message
},
)
# ここでスピーカーの音声認識を停止
self.stopTranscriptionReceiveMessage()
self.run(
400,
self.run_mapping["enable_transcription_receive"],
{
"message":"Transcription receive disabled due to VRAM overflow",
"data": False
},
)
else:
# その他のエラーは通常通り処理
errorLogging()
finally:
self.device_access_status = True self.device_access_status = True
@staticmethod @staticmethod

View File

@@ -11,6 +11,10 @@ from utils import printLog, printResponse, errorLogging, encodeBase64 # noqa: E4
logging.getLogger("huggingface_hub").setLevel(logging.ERROR) logging.getLogger("huggingface_hub").setLevel(logging.ERROR)
run_mapping = { run_mapping = {
"enable_translation":"/run/enable_translation",
"enable_transcription_send":"/run/enable_transcription_send",
"enable_transcription_receive":"/run/enable_transcription_receive",
"connected_network":"/run/connected_network", "connected_network":"/run/connected_network",
"enable_ai_models":"/run/enable_ai_models", "enable_ai_models":"/run/enable_ai_models",
@@ -22,6 +26,13 @@ run_mapping = {
"error_device":"/run/error_device", "error_device":"/run/error_device",
"error_translation_engine":"/run/error_translation_engine", "error_translation_engine":"/run/error_translation_engine",
"error_translation_chat_vram_overflow":"/run/error_translation_chat_vram_overflow",
"error_translation_mic_vram_overflow":"/run/error_translation_mic_vram_overflow",
"error_translation_speaker_vram_overflow":"/run/error_translation_speaker_vram_overflow",
"error_transcription_mic_vram_overflow":"/run/error_transcription_mic_vram_overflow",
"error_transcription_speaker_vram_overflow":"/run/error_transcription_speaker_vram_overflow",
"word_filter":"/run/word_filter", "word_filter":"/run/word_filter",
"download_progress_ctranslate2_weight":"/run/download_progress_ctranslate2_weight", "download_progress_ctranslate2_weight":"/run/download_progress_ctranslate2_weight",

View File

@@ -509,6 +509,15 @@ class Model:
if isinstance(self.mic_audio_recorder, SelectedMicEnergyAndAudioRecorder): if isinstance(self.mic_audio_recorder, SelectedMicEnergyAndAudioRecorder):
self.mic_audio_recorder.pause() self.mic_audio_recorder.pause()
# VRAM 不足エラーを検出するメソッドを追加
def detectVRAMError(self, error):
error_str = str(error)
if isinstance(error, ValueError) and len(error.args) > 0 and error.args[0] == "VRAM_OUT_OF_MEMORY":
return True, error.args[1] if len(error.args) > 1 else "VRAM out of memory"
if "CUDA out of memory" in error_str or "CUBLAS_STATUS_ALLOC_FAILED" in error_str:
return True, error_str
return False, None
def changeMicTranscriptStatus(self): def changeMicTranscriptStatus(self):
if config.VRC_MIC_MUTE_SYNC is True: if config.VRC_MIC_MUTE_SYNC is True:
match self.mic_mute_status: match self.mic_mute_status:

View File

@@ -77,7 +77,8 @@ def downloadWhisperWeight(root, weight_type, callback=None, end_callback=None):
def getWhisperModel(root, weight_type, device="cpu", device_index=0): def getWhisperModel(root, weight_type, device="cpu", device_index=0):
path = os_path.join(root, "weights", "whisper", weight_type) path = os_path.join(root, "weights", "whisper", weight_type)
compute_type = getBestComputeType(device, device_index) compute_type = getBestComputeType(device, device_index)
return WhisperModel( try:
model = WhisperModel(
path, path,
device=device, device=device,
device_index=device_index, device_index=device_index,
@@ -86,6 +87,14 @@ def getWhisperModel(root, weight_type, device="cpu", device_index=0):
num_workers=1, num_workers=1,
local_files_only=True, local_files_only=True,
) )
return model
except RuntimeError as e:
# VRAM不足エラーの検出
error_message = str(e)
if "CUDA out of memory" in error_message or "CUBLAS_STATUS_ALLOC_FAILED" in error_message:
raise ValueError("VRAM_OUT_OF_MEMORY", error_message)
# その他のエラーは通常通り再送出
raise
if __name__ == "__main__": if __name__ == "__main__":
def callback(value): def callback(value):