본문 바로가기
AI Project/Edge AI Agent - 음성처리(연구,분석,검증))

[Whisper.cpp] #1. Edge Agent AI 음성처리 : whisper.cpp를 이용한 음성처리(Base, Tiny 비교)

by 으노으뇨 2026. 4. 27.
728x90
SMALL

안녕하세요, 이번엔 whisper.cpp를 이용해서 on device, edge agent AI의 청각의 능력을 한번 분석/검증해보겠습니다.

  1. 이번 포스팅 계획은
  1. 안드로이드 + 엑시노스1380 환경에서 whisper.cpp는 잘 동작하는가?
  2. 성능은 어느정도 보장되는가?
  3. 다른 대안에 대해서 (sherpa-onnx)는 어떤가?

이렇게 3개의 꼭지로 주제를 선정하고 진행하겠습니다.


whisper.cpp 구동을 위한 필수 패키지 설치 및 최적화 빌드

Termux를 막 설치하고 실행한 순정 상태에서는 C++ 코드를 기계어로 번역할 컴파일러나 깃허브에서 코드를 가져올 도구가 전혀 없습니다.!!

따라서 다음 명령어들을 순서대로 터미널에 복사하여 실행해 주시면되겠습니다!!

pkg update && pkg upgrade -y
pkg install git clang make ffmpeg wget -y

 

  • clang: C/C++ 컴파일러입니다. 안드로이드(Termux) 환경에서는 gcc보다 clang이 표준이며, ARM 아키텍처와의 호환성이 가장 뛰어납니다.
  • make: 소스 코드를 읽어 실행 파일로 조립해 주는 필수 빌드 도구입니다.
  • ffmpeg: whisper.cpp는 엄격하게 16kHz 샘플레이트의 16-bit WAV 파일만 입력으로 받습니다. 나중에 에이전트가 스마트폰 마이크로 녹음한 m4a나 mp3 파일을 whisper가 읽을 수 있는 포맷으로 변환하기 위해 반드시 필요한 미디어 처리 프레임워크입니다.

 소스 코드 클론 및 ARM64 최적화 빌드 명령어

cd projects
# 1. whisper.cpp 공식 저장소 클론
git clone https://github.com/ggerganov/whisper.cpp.git

# 2. 작업 디렉토리로 이동
cd whisper.cpp

# 3. 엑시노스 1380(ARM64)에 최적화된 빌드 (4코어 할당)
make -j4

 

빌드까지 진행해봅니다. 오래걸립니다. 아직까진 이상없이 모두 빌드되었습니다.

# 1. 모델 다운로드 스크립트 실행 (base 모델)
bash ./models/download-ggml-model.sh base

게이지가 100%가 되고 Done! Model 'base' saved in 'models/ggml-base.bin' 이라는 메시지가 떴다면 다운로드에 성공한 것입니다.

성공했습니다. 

./build/bin/whisper-cli -m /data/data/com.termux/files/home/projects/whisper.cpp/models/ggml-base.bin -f samples/jfk.wav

명령어를 치시면, 엑시노스 1380이 방금 다운받은 뇌(모델)를 정확한 주소에서 찾아 로딩하고, 약 11초짜리 케네디 대통령의 연설을 텍스트로 토해낼 것입니다.

jfk.wav
0.34MB

존 f 케네디의 연설을 한번 돌려보겠습니다.

결과가 아주잘나왔습니다.

상세기록은 더보기에서!

더보기
➜  whisper.cpp git:(master) ./build/bin/whisper-cli -m /data/data/com.termux/files/home/projects/whisper.cpp/models/ggml-base.bin -f samples/jfk.wav
whisper_init_from_file_with_params_no_state: loading model from '/data/data/com.termux/files/home/projects/whisper.cpp/models/ggml-base.bin'
whisper_init_with_params_no_state: use gpu    = 1
whisper_init_with_params_no_state: flash attn = 1
whisper_init_with_params_no_state: gpu_device = 0
whisper_init_with_params_no_state: dtw        = 0
whisper_init_with_params_no_state: devices    = 1
whisper_init_with_params_no_state: backends   = 1
whisper_model_load: loading model
whisper_model_load: n_vocab       = 51865
whisper_model_load: n_audio_ctx   = 1500
whisper_model_load: n_audio_state = 512
whisper_model_load: n_audio_head  = 8
whisper_model_load: n_audio_layer = 6
whisper_model_load: n_text_ctx    = 448
whisper_model_load: n_text_state  = 512
whisper_model_load: n_text_head   = 8
whisper_model_load: n_text_layer  = 6
whisper_model_load: n_mels        = 80
whisper_model_load: ftype         = 1
whisper_model_load: qntvr         = 0
whisper_model_load: type          = 2 (base)
whisper_model_load: adding 1608 extra tokens
whisper_model_load: n_langs       = 99
whisper_model_load:          CPU total size =   147.37 MB
whisper_model_load: model size    =  147.37 MB
whisper_backend_init_gpu: device 0: CPU (type: 0)
whisper_backend_init_gpu: no GPU found
whisper_init_state: kv self size  =    6.29 MB
whisper_init_state: kv cross size =   18.87 MB
whisper_init_state: kv pad  size  =    3.15 MB
whisper_init_state: compute buffer (conv)   =   16.28 MB
whisper_init_state: compute buffer (encode) =   23.09 MB
whisper_init_state: compute buffer (cross)  =    4.66 MB
whisper_init_state: compute buffer (decode) =   96.37 MB

system_info: n_threads = 4 / 8 | WHISPER : COREML = 0 | OPENVINO = 0 | CPU : NEON = 1 | ARM_FMA = 1 | FP16_VA = 1 | DOTPROD = 1 | OPENMP = 1 | REPACK = 1 |

main: processing 'samples/jfk.wav' (176000 samples, 11.0 sec), 4 threads, 1 processors, 5 beams + best of 5, lang = en, task = transcribe, timestamps = 1 ...


[00:00:00.000 --> 00:00:10.500]   And so my fellow Americans ask not what your country can do for you, ask what you can do for your country.

whisper_print_timings:     load time =  1042.02 ms
whisper_print_timings:     fallbacks =   0 p /   0 h
whisper_print_timings:      mel time =    69.04 ms
whisper_print_timings:   sample time =  1004.74 ms /   137 runs (     7.33 ms per run)
whisper_print_timings:   encode time = 11479.74 ms /     1 runs ( 11479.74 ms per run)
whisper_print_timings:   decode time =    92.41 ms /     2 runs (    46.20 ms per run)
whisper_print_timings:   batchd time =  3425.27 ms /   133 runs (    25.75 ms per run)
whisper_print_timings:   prompt time =     0.00 ms /     1 runs (     0.00 ms per run)
whisper_print_timings:    total time = 17252.62 ms

결과

하드웨어 가속 활용도: 최상 (100점)

CPU : NEON = 1 | ARM_FMA = 1 | FP16_VA = 1 | DOTPROD = 1 | OPENMP = 1

이 로그가 프로젝트의 가장 큰 수확 중 하나입니다!!!

안드로이드 순정 Termux 환경에서 C++로 직접 빌드한 결과, 엑시노스 1380의 핵심 가속기(NEON, FMA, FP16, DOTPROD)가 단 하나도 빠짐없이 100% 활성화되었습니다!!!

즉, 기기가 낼 수 있는 최대의 연산 효율을 끌어내고 있다는 뜻입니다!!!

지난번 BitNet 처럼 빙빙돌아가지 않아도 되었습니다 ㅠㅠㅠㅠㅠ

메모리 점유율 (RAM): 최상 (매우 가벼움)

model size = 147.37 MB / compute buffer (decode) = 96.37 MB

분석: 전체 STT 엔진이 구동되는 데 스마트폰 RAM을 고작 250MB~300MB 남짓 사용합니다.

백그라운드에 항상 켜두고 대기시켜야 하는 AMEVA 에이전트의 귀 모듈로서 메모리 효율은 합격점을 훌쩍 넘습니다.

처리 속도 (Real-Time Factor, RTF): 다소 아쉬움 (병목 지점)

11.0 sec (샘플 길이) ↔ total time = 17252.62 ms (약 17.25초)
encode time = 11479.74 ms (약 11.4초)

분석: 업계에서는 음성 인식 속도를 평가할 때 **RTF(Real-Time Factor)**라는 공식을 씁니다. (처리 시간 ÷ 오디오 길이).

현재 RTF는 17.25 / 11 = 약 1.57 입니다. 즉, 1초짜리 음성을 번역하는 데 1.57초가 걸린다는 뜻입니다.ㅠㅠㅠ

가장 큰 병목은 encode time(11.4초)입니다.

오디오 파형을 AI가 이해할 수 있는 벡터로 변환하는 데에만 오디오 원본 길이보다 긴 시간이 소요되었습니다.

만약 사용자가 에이전트에게 5초 동안 명령을 내리면, 대답을 듣기 전 텍스트로 변환하는 데만 8초 가까이 기다려야 하므로 답답함을 느낄 수 있습니다.


Tiny 모델로 진행

RTF가 1초를 초과하여 성능이 안좋았어서 한번 Tiny 모델로 다시 설치해서 진행해보겠습니다.

# 1. tiny 모델 다운로드 (약 75MB)
bash ./models/download-ggml-model.sh tiny

# 2. tiny 모델로 동일한 파일 추론 (속도 비교용)
./build/bin/whisper-cli -m /data/data/com.termux/files/home/projects/whisper.cpp/models/ggml-tiny.bin -f samples/jfk.wav

출력값에 대해서는 문제는 없어보입니다.

총 처리 시간: 8.85초 (8854 ms) -> RTF 0.80 (대합격!)

상세기록은 더보기에서!!

더보기

기록은 이렇습니다.

whisper_init_from_file_with_params_no_state: loading model from '/data/data/com.termux/files/home/projects/whisper.cpp/models/ggml-tiny.bin'
whisper_init_with_params_no_state: use gpu    = 1
whisper_init_with_params_no_state: flash attn = 1
whisper_init_with_params_no_state: gpu_device = 0
whisper_init_with_params_no_state: dtw        = 0
whisper_init_with_params_no_state: devices    = 1
whisper_init_with_params_no_state: backends   = 1
whisper_model_load: loading model
whisper_model_load: n_vocab       = 51865
whisper_model_load: n_audio_ctx   = 1500
whisper_model_load: n_audio_state = 384
whisper_model_load: n_audio_head  = 6
whisper_model_load: n_audio_layer = 4
whisper_model_load: n_text_ctx    = 448
whisper_model_load: n_text_state  = 384
whisper_model_load: n_text_head   = 6
whisper_model_load: n_text_layer  = 4
whisper_model_load: n_mels        = 80
whisper_model_load: ftype         = 1
whisper_model_load: qntvr         = 0
whisper_model_load: type          = 1 (tiny)
whisper_model_load: adding 1608 extra tokens
whisper_model_load: n_langs       = 99
whisper_model_load:          CPU total size =    77.11 MB
whisper_model_load: model size    =   77.11 MB
whisper_backend_init_gpu: device 0: CPU (type: 0)
whisper_backend_init_gpu: no GPU found
whisper_init_state: kv self size  =    3.15 MB
whisper_init_state: kv cross size =    9.44 MB
whisper_init_state: kv pad  size  =    2.36 MB
whisper_init_state: compute buffer (conv)   =   13.21 MB
whisper_init_state: compute buffer (encode) =   17.72 MB
whisper_init_state: compute buffer (cross)  =    3.89 MB
whisper_init_state: compute buffer (decode) =   95.91 MB

system_info: n_threads = 4 / 8 | WHISPER : COREML = 0 | OPENVINO = 0 | CPU : NEON = 1 | ARM_FMA = 1 | FP16_VA = 1 | DOTPROD = 1 | OPENMP = 1 | REPACK = 1 |

main: processing 'samples/jfk.wav' (176000 samples, 11.0 sec), 4 threads, 1 processors, 5 beams + best of 5, lang = en, task = transcribe, timestamps = 1 ...


[00:00:00.000 --> 00:00:10.500]   And so, my fellow Americans, ask not what your country can do for you, ask what you can do for your country.

whisper_print_timings:     load time =   336.39 ms
whisper_print_timings:     fallbacks =   0 p /   0 h
whisper_print_timings:      mel time =    71.43 ms
whisper_print_timings:   sample time =  1463.39 ms /   138 runs (    10.60 ms per run)
whisper_print_timings:   encode time =  4906.99 ms /     1 runs (  4906.99 ms per run)
whisper_print_timings:   decode time =     0.00 ms /     1 runs (     0.00 ms per run)
whisper_print_timings:   batchd time =  1992.92 ms /   136 runs (    14.65 ms per run)
whisper_print_timings:   prompt time =     0.00 ms /     1 runs (     0.00 ms per run)
whisper_print_timings:    total time =  8854.66 ms

분석 비교! Base vs Tiny!!

실시간성 비교

비교 항목 (Metrics) Whisper base (약 74M) Whisper tiny (약 39M) 최적화 결과 및 평가
모델 메모리 (RAM) 147.37 MB 77.11 MB 약 47% 감소 (모바일 백그라운드 최적화)
초기 로딩 (Load time) 1,042 ms (약 1초) 336 ms (0.3초) 3.1배 속도 향상 (즉각적인 뇌 활성화)
오디오 인코딩 시간 11.4초 4.9초 2.3배 단축 (가장 심한 병목 구간 해소)
총 처리 시간 (Total) 17.25초 8.85초 총 소요시간 절반으로 단축
RTF (실시간 지수) 1.57 (실시간 대화 불가) 0.80 (실시간 대화 가능) 대합격 (기계가 사람의 말을 기다림)

만약에! 실시간으로 변환하지 않고 특정시간에 배치작업으로 전환한다면 

small 이나 medium 모델도 적합할 것같습니다.

다음 분석/검증으로는 한국어도 과연 잘처리하나 보겠습니다!!

긴글 읽어주셔서 감사합니다.

 

728x90
LIST

댓글