OpenAI Whisper Streaming API - websocket

Stuart Kim·2025년 5월 12일
post-thumbnail

STT 혹은 ASR을 실시간으로 붙여야 하는 상황이 많아졌다.
위스퍼 모델은 오픈소스이니 온프렘으로 구축할 수는 있지만 역시 인프라, 비용이 문제다.
API를 사용하는게 더 저렴한 경우가 있다.

아래는 OpenAI의 Whisper 모델을 websocket 방식으로 통신하는 streaming transcription 코드에 대해 작성한다.


설치

아래 테스트는 파일 넣고 하는 것보다 실시간으로 내 음성을 입력으로 받는 것을 원해서 마이크 입력 콘솔 출력을 원칙으로 개발하였다.

맥북 기준으로 마이크와 웹소켓 관련 라이브러리 설치가 필요하다.

brew install sox
npm install ws mic

javascript 코드

파이썬이 주언어이긴 하지만 클라이언트 개발자가 요청하면 자바스크립트도 하는 거시 개발자의 숙명띠라서 자바스크립트 코드로 알아보았다.

const WebSocket = require('ws');
const mic = require('mic');

// OpenAI API 키 설정 (환경변수에서 가져오기)
const apiKey = null;

if (!apiKey) {
  console.error('환경변수 OPENAI_API_KEY를 설정하세요.');
  process.exit(1);
}

// WebSocket 연결 설정
const ws = new WebSocket('wss://api.openai.com/v1/realtime?intent=transcription', {
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'OpenAI-Beta': 'realtime=v1'
  }
});

// 마이크 설정 (PCM 16-bit mono 16kHz)
const micInstance = mic({
  rate: '16000',
  channels: '1',
  bitwidth: '16',
  encoding: 'signed-integer',
  endian: 'little',
  fileType: 'raw'
});
const micInputStream = micInstance.getAudioStream();

// WebSocket이 열리면 OpenAI에 세션 초기화 정보 전송 및 마이크 시작
ws.on('open', () => {
  console.log('OpenAI WebSocket 연결됨.');

  const sessionConfig = {
    type: 'transcription_session.update',
    session: {
      input_audio_format: 'pcm16',
      input_audio_transcription: {
        model: 'whisper-1',
        language: 'ko' // 한국어 인식
      },
      turn_detection: { type: 'server_vad' },
      input_audio_noise_reduction: { type: 'near_field' }
    }
  };
  ws.send(JSON.stringify(sessionConfig));
  console.log('전사 세션 설정 완료.');

  micInstance.start();
  console.log('마이크 입력 시작...');
});

// 마이크 오디오 데이터를 WebSocket으로 전송
micInputStream.on('data', (audioBuffer) => {
  const audioBase64 = audioBuffer.toString('base64');
  const audioMessage = {
    type: 'input_audio_buffer.append',
    audio: audioBase64
  };
  if (ws.readyState === WebSocket.OPEN) {
    ws.send(JSON.stringify(audioMessage));
  }
});

// 마이크 에러 처리
micInputStream.on('error', (err) => {
  console.error('마이크 에러:', err);
});

// WebSocket에서 전사 결과 메시지 수신 및 출력
ws.on('message', (data) => {
  const msg = JSON.parse(data);
  switch (msg.type) {
    case 'conversation.item.input_audio_transcription.partial':
      console.log('🔹 [진행 중]:', msg.transcript);
      break;
    case 'conversation.item.input_audio_transcription.completed':
      console.log('🔸 [완료]:', msg.transcript);
      break;
    case 'input_audio_buffer.speech_started':
      console.log('(🟢 음성 시작 감지)');
      break;
    case 'input_audio_buffer.speech_stopped':
      console.log('(🔴 음성 종료 감지)');
      break;
    default:
      console.log('기타 메시지:', msg);
      break;
  }
});

// WebSocket 종료 처리
ws.on('close', () => {
  console.log('WebSocket 연결 종료됨.');
  micInstance.stop();
});

// WebSocket 에러 처리
ws.on('error', (err) => {
  console.error('WebSocket 에러:', err);
});

출력값

아래처럼 나온다.

...(생략)...

🔸 [완료]: 안녕

...(생략)...

주의사항

Openai의 streaming API 사용할 때는 일반적인 openai API 사용할 때와 다르다. 미리 크레딧을 구매한 후에 사용 가능하다.
크레딧이 없을 경우 아래 에러들이 발생한다.

"type": "server_error",
"code": null,
"message": "The server had an error while processing your request. Sorry about that! You can retry your request, or contact us through our help center at help.openai.com if the error persists.
Input transcription failed for item 'item_ajdflkajhlekw'. 429 Too Many Requests

References

profile
AI Engineer 의 개발 블로그입니다!

0개의 댓글