Files
CavinHuang-comfyui-nodes-docs/docs/SAIOpenAIAPIWhisper.md
2024-07-04 08:39:03 +08:00

211 lines
8.2 KiB
Markdown

# Documentation
- Class name: SAIOpenAIAPIWhisper
- Category: SALT/Whisper
- Output node: False
- Repo Ref: https://github.com/comfyanonymous/ComfyUI
SAIOpenAIAPIWhisper节点使用OpenAI的Whisper API提供音频内容的转录或翻译功能。它支持各种配置选项,包括模型选择、响应格式和温度设置,以根据特定需求定制转录或翻译过程。
# Input types
## Required
- file_path
- 要转录或翻译的音频文件路径。这个参数对于定位和处理音频内容至关重要。
- Comfy dtype: STRING
- Python dtype: str
- openai_key
- OpenAI的API密钥,用于验证对Whisper API的请求。
- Comfy dtype: STRING
- Python dtype: str
## Optional
- model
- 指定用于转录或翻译的Whisper模型,允许根据模型能力定制处理过程。
- Comfy dtype: COMBO[STRING]
- Python dtype: str
- mode
- 指定操作是转录还是翻译音频内容,提供处理灵活性。
- Comfy dtype: COMBO[STRING]
- Python dtype: str
- language
- 音频内容的语言,可以影响转录或翻译的准确性。
- Comfy dtype: STRING
- Python dtype: str
- response_format
- 确定转录或翻译输出的格式,支持文本或JSON格式以实现灵活集成。
- Comfy dtype: COMBO[STRING]
- Python dtype: str
- temperature
- 调整转录或翻译输出的创造性或可变性,能够微调结果。
- Comfy dtype: FLOAT
- Python dtype: float
- timestamp_granularities
- 定义转录中时间戳的详细程度,允许段落或单词级别的粒度。
- Comfy dtype: COMBO[STRING]
- Python dtype: str
- max_frames
- 要处理的最大帧数,能够控制转录或翻译的范围。
- Comfy dtype: INT
- Python dtype: int
- seek_seconds
- 开始转录或翻译前在音频中寻找的秒数,允许精确设置起始点。
- Comfy dtype: FLOAT
- Python dtype: float
- prompt
- 可选的提示,可以引导转录或翻译过程,为模型提供上下文或指令。
- Comfy dtype: STRING
- Python dtype: str
# Output types
- transcription_result
- 最终的转录或翻译文本输出。
- Comfy dtype: STRING
- Python dtype: str
- audio_path
- 处理后的音频文件路径,对后续操作或验证有用。
- Comfy dtype: STRING
- Python dtype: str
- frames_count
- 转录或翻译过程中处理的帧数,提供操作范围的洞察。
- Comfy dtype: INT
- Python dtype: int
## Usage tips
- Infra type: `CPU`
- Common nodes: unknown
## Source code
```python
class SAIOpenAIAPIWhisper:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"file_path": ("STRING", {}),
"openai_key": ("STRING", {}),
},
"optional": {
"model": (["whisper-1"],),
"mode": (["transcribe", "translate_to_english"],),
"language": ("STRING", {}),
"response_format": (["text", "json", "verbose_json", "prompt_schedule"],),
"temperature": ("FLOAT", {"min": 0.0, "max": 1.0, "default": 0.7}),
"timestamp_granularities": (["segment", "word"],),
"max_frames": ("INT", {"default": 0, "min": 0}),
"seek_seconds": ("FLOAT", {"default": 0.0}),
"prompt": ("STRING", {"multiline": True, "placeholder": "Optional prompt..."})
}
}
RETURN_TYPES = ("STRING", "STRING", "INT")
RETURN_NAMES = ("transcription_result", "audio_path", "frames_count")
FUNCTION = "whisper_v2"
CATEGORY = "SALT/Whisper"
def whisper_v2(self, file_path, openai_key, model="whisper-1", mode="transcribe", language="", response_format="text", temperature=0.7, timestamp_granularities="segment", max_frames=0, seek_seconds=0.0, prompt=""):
language = language if language else None
prompt = prompt if prompt else None
file_path = os.path.join(INPUT, file_path)
if not os.path.exists(file_path):
raise ValueError(f"The specified file `{file_path}` does not exist!")
if model not in ("whisper-1"):
raise ValueError(f"The specified model `{model}` does not exist!")
if mode not in ("transcribe", "translate_to_english"):
print(f'The `mode` selected "{mode}" is not valid. Please use either "transcribe", or "translate_to_english"')
mode = "transcribe"
openai.api_key = openai_key
audio_path, fps, total_frames = self.extract_audio(file_path)
max_frames = max_frames if max_frames != 0 else total_frames
match mode:
case "transcribe":
if response_format == "prompt_schedule":
transcription = self.transcribe_audio(file_path, model, prompt, language, "verbose_json", temperature, timestamp_granularities, json_string=False)
out = self.prompt_schedule(transcription, fps, max_frames, seek_seconds)
else:
out = self.transcribe_audio(file_path, model, prompt, language, response_format, temperature, timestamp_granularities)
case "translate_to_english":
out = self.translate_audio(file_path, model, prompt, response_format, temperature)
return (out, audio_path, total_frames)
def transcribe_audio(self, file_path, model="whisper-1", prompt=None, language=None, response_format="json", temperature=0.7, timestamp_granularities="segment", json_string=True):
with open(file_path, "rb") as audio_file:
response = openai.audio.transcriptions.create(
model=model,
file=audio_file,
prompt=prompt,
response_format=response_format,
language=language,
temperature=temperature,
timestamp_granularities=timestamp_granularities
)
from pprint import pprint
pprint(response, indent=4)
if response_format in ("json", "verbose_json"):
segments = getattr(response, 'segments', [])
if json_string:
out = json.dumps(segments, ensure_ascii=True, indent=4)
else:
out = segments
else:
out = response
return out
def translate_audio(self, file_path, model="whisper-1", prompt=None, response_format="json", temperature=0.7):
with open(file_path, "rb") as audio_file:
response = openai.audio.translations.create(
model=model,
file=audio_file,
prompt=prompt,
response_format=response_format,
temperature=temperature,
)
from pprint import pprint
pprint(response, indent=4)
if response_format in ("json", "verbose_json"):
segments = getattr(response, 'segments', [])
out = json.dumps(segments, ensure_ascii=True, indent=4)
else:
out = response
return out
def extract_audio(self, file_path):
clip = VideoFileClip(file_path)
fps = clip.fps
total_frames = int(clip.duration * fps)
audio_path = os.path.join(OUTPUT, f"{os.path.splitext(os.path.basename(file_path))[0]}.mp3")
clip.audio.write_audiofile(audio_path)
clip.close()
return audio_path, fps, total_frames
def prompt_schedule(self, transcription, fps, max_frames, seek_seconds):
prompt_schedule = ""
max_seconds = max_frames / fps if max_frames > 0 else float('inf')
start_frame = int(seek_seconds * fps)
if isinstance(transcription, list):
for idx, segment in enumerate(transcription):
segment_start = segment.get("start", 0.0)
if segment_start < seek_seconds or segment_start > max_seconds:
continue
frame_number = int(segment_start * fps) - start_frame
text = segment.get("text", "")
if frame_number >= 0:
prompt_schedule += f'"{frame_number}": "{text.strip()}"' + (",\n" if idx != len(transcription) else "\n")
return prompt_schedule
```