음성-텍스트 변환 API

음성-텍스트 변환 API (Speech to Text APIs)

vLLM의 Speech to Text API는 Transcriptions(받아쓰기)·Translations(번역)·Realtime(실시간 WebSocket) 세 가지를 제공합니다. Transcriptions/Translations는 OpenAI의 해당 API와 호환되어 공식 OpenAI Python 클라이언트로 사용할 수 있습니다.

출처: 문서

본문

Transcriptions API

Transcriptions API는 OpenAI의 Transcriptions API와 호환됩니다. 공식 OpenAI Python 클라이언트로 상호작용할 수 있습니다.

참고

Transcriptions API를 사용하려면 오디오 의존성을 포함해 pip install vllm[audio]로 설치하세요.

코드 예시: examples/speech_to_text/openai/openai_transcription_client.py

참고: beam search는 현재 whisper 같은 encoder-decoder 멀티모달 모델의 transcriptions 엔드포인트에서 지원되지만, encoder/decoder 캐시 처리를 위한 작업이 진행 중이라 매우 비효율적입니다. 이는 지속적인 최적화 지점이며 곧 제대로 처리될 예정입니다.

API 강제 한계 (API Enforced Limits)

vLLM이 수용할 최대 오디오 파일 크기(MB)는 VLLM_MAX_AUDIO_CLIP_FILESIZE_MB 환경 변수로 설정합니다. 기본값은 25MB입니다.

오디오 파일 업로드

Transcriptions API는 FLAC, MP3, MP4, MPEG, MPGA, M4A, OGG, WAV, WEBM 등 다양한 형식의 오디오 파일 업로드를 지원합니다.

OpenAI Python 클라이언트 사용:

from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:8000/v1",
    api_key="token-abc123",
)

# Upload audio file from disk
with open("audio.mp3", "rb") as audio_file:
    transcription = client.audio.transcriptions.create(
        model="openai/whisper-large-v3-turbo",
        file=audio_file,
        language="en",
        response_format="verbose_json",
    )

print(transcription.text)

curl과 multipart/form-data 사용:

curl -X POST "http://localhost:8000/v1/audio/transcriptions" \
  -H "Authorization: Bearer ***" \
  -F "[email protected]" \
  -F "model=openai/whisper-large-v3-turbo" \
  -F "language=en" \
  -F "response_format=verbose_json"

지원 파라미터:

  • file: 전사할 오디오 파일 (필수)
  • model: 전사에 사용할 모델 (필수)
  • language: 언어 코드(예: "en", "zh") (선택)
  • prompt: 전사 스타일을 안내하는 선택적 텍스트 (선택)
  • response_format: 응답 형식("json", "text", "verbose_json", 또는 "diarized_json") (선택)
  • temperature: 0과 1 사이의 샘플링 온도 (선택)

샘플링 파라미터와 vLLM 확장을 포함한 지원 파라미터 전체 목록은 protocol 정의를 참고하세요.

응답 형식:

verbose_json 응답 형식:

{
  "text": "Hello, this is a transcription of the audio file.",
  "language": "en",
  "duration": 5.42,
  "segments": [
    {
      "id": 0,
      "seek": 0,
      "start": 0.0,
      "end": 2.5,
      "text": "Hello, this is a transcription",
      "tokens": [50364, 938, 428, 307, 275, 28347],
      "temperature": 0.0,
      "avg_logprob": -0.245,
      "compression_ratio": 1.235,
      "no_speech_prob": 0.012
    }
  ]
}

현재 "verbose_json" 응답 형식은 no_speech_prob를 지원하지 않습니다.

다이아라이제이션(diarization)을 지원하는 모델의 경우 diarized_json이 OpenAI 호환 화자 세그먼트를 반환합니다. 현재 OpenMOSS-Team/MOSS-Transcribe-Diarize가 이를 지원합니다.

{
  "task": "transcribe",
  "duration": 6.1,
  "text": "Hello. Hi, how are you?",
  "segments": [
    {
      "type": "transcript.text.segment",
      "id": "segment_0",
      "start": 0.0,
      "end": 2.8,
      "text": "Hello.",
      "speaker": "S01"
    }
  ],
  "usage": {"type": "duration", "seconds": 7}
}

추가 파라미터

다음 샘플링 파라미터가 지원됩니다.

    use_beam_search: bool = False
    """Whether or not beam search should be used."""

    n: int = 1
    """The number of beams to be used in beam search."""

    length_penalty: float = 1.0
    """Length penalty to be used for beam search."""

    include_stop_str_in_output: bool = False
    """Whether to include the stop strings in output text."""

    temperature: float = Field(default=0.0)
    """The sampling temperature, between 0 and 1.

    Higher values like 0.8 will make the output more random, while lower values
    like 0.2 will make it more focused / deterministic. If set to 0, the model
    will use [log probability](https://en.wikipedia.org/wiki/Log_probability)
    to automatically increase the temperature until certain thresholds are hit.
    """

    top_p: float | None = None
    """Enables nucleus (top-p) sampling, where tokens are selected from the
    smallest possible set whose cumulative probability exceeds `p`.
    """

    top_k: int | None = None
    """Limits sampling to the `k` most probable tokens at each step."""

    min_p: float | None = None
    """Filters out tokens with a probability lower than `min_p`, ensuring a
    minimum likelihood threshold during sampling.
    """

    seed: int | None = Field(None, ge=_LONG_INFO.min, le=_LONG_INFO.max)
    """The seed to use for sampling."""

    frequency_penalty: float | None = 0.0
    """The frequency penalty to use for sampling."""

    repetition_penalty: float | None = None
    """The repetition penalty to use for sampling."""

    presence_penalty: float | None = 0.0
    """The presence penalty to use for sampling."""

    max_completion_tokens: int | None = None
    """The maximum number of tokens to generate."""

다음 추가 파라미터도 지원됩니다:

    # Flattened stream option to simplify form data.
    stream_include_usage: bool | None = False
    stream_continuous_usage_stats: bool | None = False

    vllm_xargs: dict[str, str | int | float | list[str | int | float]] | None = Field(
        default=None,
        description=(
            "Additional request parameters with (list of) string or "
            "numeric values, used by custom extensions."
        ),
    )

Translations API

Translation API는 OpenAI의 Translations API와 호환됩니다. 공식 OpenAI Python 클라이언트로 상호작용할 수 있습니다. Whisper 모델은 지원되는 55개 비영어 언어 중 하나의 오디오를 영어로 번역할 수 있습니다. 인기 있는 openai/whisper-large-v3-turbo 모델은 번역을 지원하지 않는다는 점에 주의하세요.

참고

Translation API를 사용하려면 오디오 의존성을 포함해 pip install vllm[audio]로 설치하세요.

코드 예시: examples/speech_to_text/openai/openai_translation_client.py

추가 파라미터

다음 샘플링 파라미터가 지원됩니다.

    use_beam_search: bool = False
    """Whether or not beam search should be used."""

    n: int = 1
    """The number of beams to be used in beam search."""

    length_penalty: float = 1.0
    """Length penalty to be used for beam search."""

    include_stop_str_in_output: bool = False
    """Whether to include the stop strings in output text."""

    seed: int | None = Field(None, ge=_LONG_INFO.min, le=_LONG_INFO.max)
    """The seed to use for sampling."""

    temperature: float = Field(default=0.0)
    """The sampling temperature, between 0 and 1.

    Higher values like 0.8 will make the output more random, while lower values
    like 0.2 will make it more focused / deterministic. If set to 0, the model
    will use [log probability](https://en.wikipedia.org/wiki/Log_probability)
    to automatically increase the temperature until certain thresholds are hit.
    """

    top_p: float | None = None
    """Enables nucleus (top-p) sampling, where tokens are selected from the
    smallest possible set whose cumulative probability exceeds `p`.
    """

    top_k: int | None = None
    """Limits sampling to the `k` most probable tokens at each step."""

    min_p: float | None = None
    """Filters out tokens with a probability lower than `min_p`, ensuring a
    minimum likelihood threshold during sampling.
    """

    frequency_penalty: float | None = 0.0
    """The frequency penalty to use for sampling."""

    repetition_penalty: float | None = None
    """The repetition penalty to use for sampling."""

    presence_penalty: float | None = 0.0
    """The presence penalty to use for sampling."""

다음 추가 파라미터가 지원됩니다:

    language: str | None = None
    """The language of the input audio we translate from.

    Supplying the input language in
    [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) format
    will improve accuracy.
    """

    hotwords: str | None = None
    """
    hotwords refers to a list of important words or phrases that the model
    should pay extra attention to during transcription.
    """

    to_language: str | None = None
    """The language of the input audio we translate to.

    Please note that this is not supported by all models, refer to the specific
    model documentation for more details.
    For instance, Whisper only supports `to_language=en`.
    """

    stream: bool | None = False
    """Custom field not present in the original OpenAI definition. When set,
    it will enable output to be streamed in a similar fashion as the Chat
    Completion endpoint.
    """
    # Flattened stream option to simplify form data.
    stream_include_usage: bool | None = False
    stream_continuous_usage_stats: bool | None = False

    max_completion_tokens: int | None = None
    """The maximum number of tokens to generate."""

    vllm_xargs: dict[str, str | int | float | list[str | int | float]] | None = Field(
        default=None,
        description=(
            "Additional request parameters with (list of) string or "
            "numeric values, used by custom extensions."
        ),
    )

Realtime API

Realtime API는 WebSocket 기반 스트리밍 오디오 전사를 제공해, 오디오가 녹음되는 동안 실시간으로 음성을 텍스트로 바꿉니다.

참고

Realtime API를 사용하려면 오디오 의존성을 포함해 uv pip install vllm[audio]로 설치하세요.

오디오 형식

오디오는 16kHz 샘플레이트, 모노 채널의 base64 인코딩 PCM16 오디오로 보내야 합니다.

프로토콜 개요

  1. 클라이언트가 ws://host/v1/realtime에 연결
  2. 서버가 session.created 이벤트 전송
  3. 클라이언트가 선택적으로 모델/파라미터로 session.update 전송
  4. 클라이언트가 준비되면 input_audio_buffer.commit 전송
  5. 클라이언트가 base64 PCM16 청크로 input_audio_buffer.append 이벤트 전송
  6. 서버가 증분 텍스트로 transcription.delta 이벤트 전송
  7. 서버가 최종 텍스트 + usage로 transcription.done 전송
  8. 다음 발화에 대해 5단계부터 반복
  9. 선택적으로 클라이언트가 final=Trueinput_audio_buffer.commit을 보내 오디오 입력 종료를 알림. 오디오 파일을 스트리밍할 때 유용

클라이언트 → 서버 이벤트

이벤트 설명
input_audio_buffer.append base64 인코딩 오디오 청크 전송: {"type": "input_audio_buffer.append", "audio": "<base64>"}
input_audio_buffer.commit 전사 처리를 트리거하거나 종료: {"type": "input_audio_buffer.commit", "final": bool}
session.update 세션 구성: {"type": "session.update", "model": "model-name"}

서버 → 클라이언트 이벤트

이벤트 설명
session.created 세션 ID와 타임스탬프로 연결 확립
transcription.delta 증분 전사 텍스트: {"type": "transcription.delta", "delta": "text"}
transcription.done usage 통계와 함께 최종 전사
error 메시지와 선택적 코드가 포함된 오류 알림

예시 클라이언트

더 알아보기 (Learn more)