AI Sparkup

최신 AI 쉽게 깊게 따라잡기⚡

Transformers.js 튜토리얼 – 브라우저에서 이미지 분류·캡셔닝·음성 인식 멀티모달 앱 만들기

transformersjs로 서버 없이 브라우저에서만 동작하는 멀티모달 AI 앱을 만드는 실전 튜토리얼이다. 이미지 분류, 이미지 캡셔닝, 음성 전사 세 파이프라인을 단계별로 구현하고, 마지막에 세 기능을 하나의 미디어 분석기로 통합한다. 모든 모델은 사용자 브라우저에서 로컬로 실행되며 API 키나 서버가 필요 없다.

사용 모델

태스크모델파이프라인 타입첫 다운로드 크기
이미지 분류Xenova/vit-base-patch16-224image-classification~88 MB
이미지 캡셔닝Xenova/vit-gpt2-image-captioningimage-to-text~246 MB
음성 전사Xenova/whisper-tiny.enautomatic-speech-recognition~78 MB

세 모델을 모두 로드하면 첫 실행 시 약 400 MB를 다운로드한다. 이후에는 브라우저 캐시에 저장되어 오프라인에서도 즉시 로드된다.

시작하기 전 준비

Transformers.js는 모듈 방식으로 사용하므로 로컬 웹 서버가 필요하다.

# Python 3
python -m http.server 8000

# Node.js
npx serve .

각 태스크는 <script type="module"> 태그를 사용하는 독립적인 HTML 파일로 구성된다.

Task 1: 이미지 분류 (Image Classification)

Vision Transformer 모델(ViT-Base)을 사용해 이미지에서 객체를 분류하고 확률값을 반환한다.

<script type="module">
import { pipeline } from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@3/dist/transformers.min.js';

const classifier = await pipeline(
  'image-classification',
  'Xenova/vit-base-patch16-224'
);

const results = await classifier('/path/to/image.jpg', { topk: 5 });
// 결과: [{ label: 'golden retriever', score: 0.942 }, ...]
</script>

결과는 레이블과 확률 점수 배열로 반환된다 (예: "golden retriever, 94.2%").

Task 2: 이미지 캡셔닝 (Image Captioning)

ViT-GPT2 모델로 이미지를 설명하는 자연어 문장을 생성한다.

<script type="module">
import { pipeline } from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@3/dist/transformers.min.js';

const captioner = await pipeline(
  'image-to-text',
  'Xenova/vit-gpt2-image-captioning'
);

const result = await captioner('/path/to/image.jpg');
// 결과: [{ generated_text: "a dog is playing on a tennis court." }]
</script>

이미지 분류와 캡셔닝은 모델 가중치를 공유하지 않으므로 Promise.all로 두 추론을 병렬 실행하면 시간을 절약할 수 있다.

Task 3: 음성 전사 (Speech Transcription)

Whisper 아키텍처 기반 whisper-tiny.en 모델을 WebAssembly로 실행한다. Web Audio API로 마이크 입력을 받아 Whisper 필요 포맷(16kHz, Float32Array)으로 변환한다.

async function decodeAudio(arrayBuffer) {
  const ctx = new AudioContext({ sampleRate: 16000 }); // Whisper 필수 샘플레이트
  const audioBuffer = await ctx.decodeAudioData(arrayBuffer);
  return audioBuffer.getChannelData(0); // Float32Array
}

주요 설정:

  • sampleRate: 16000 — Whisper 모델의 필수 입력 형식
  • chunk_length_s: 30 — 30초 단위 처리, 5초 오버랩으로 경계 단어 누락 방지
  • 지원 포맷: WAV, MP3, MP4, OGG, FLAC
const transcriber = await pipeline(
  'automatic-speech-recognition',
  'Xenova/whisper-tiny.en'
);

const result = await transcriber(float32Array, {
  chunk_length_s: 30,
  stride_length_s: 5
});

최종 통합: 멀티모달 미디어 분석기

세 파이프라인을 하나의 앱(media-analyzer.html)으로 통합한다. 페이지 열자마자 세 모델이 병렬 로드를 시작하며, 모두 준비된 후에야 UI가 활성화된다.

// 세 파이프라인 병렬 로드
const [classifier, captioner, transcriber] = await Promise.all([
  pipeline('image-classification', 'Xenova/vit-base-patch16-224'),
  pipeline('image-to-text', 'Xenova/vit-gpt2-image-captioning'),
  pipeline('automatic-speech-recognition', 'Xenova/whisper-tiny.en')
]);

앱 동작 방식:

  • 이미지 업로드 시: 분류와 캡셔닝을 병렬 실행 → 동일 결과 그리드에 표시
  • 마이크 입력 시: 음성 전사 실행 → 결과 카드 표시
  • 헤더 배지: 각 모델의 로드 완료 상태를 실시간 표시

핵심 패턴 정리

패턴설명
Promise.all 병렬 로드독립적인 모델/추론은 항상 병렬로 실행해 대기 시간 단축
브라우저 캐시 활용첫 다운로드 후 재실행 시 오프라인에서도 즉시 사용
AudioContext sampleRate: 16000Whisper 모델의 필수 입력 샘플레이트
로컬 서버 필요ES 모듈 방식이므로 file:// 프로토콜로는 동작하지 않음

참고 자료



AI Sparkup 구독하기

최신 게시물 요약과 더 심층적인 정보를 이메일로 받아 보세요! (무료)