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

- 이번 포스팅 계획은
- 안드로이드 + 엑시노스1380 환경에서 whisper.cpp는 잘 동작하는가?
- 성능은 어느정도 보장되는가?
- 다른 대안에 대해서 (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초짜리 케네디 대통령의 연설을 텍스트로 토해낼 것입니다.
존 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 모델도 적합할 것같습니다.
다음 분석/검증으로는 한국어도 과연 잘처리하나 보겠습니다!!
긴글 읽어주셔서 감사합니다.

'AI Project > Edge AI Agent - 음성처리(연구,분석,검증))' 카테고리의 다른 글
| [비교/검증-3] #5. Edge Agent AI 음성처리 : Pyannote 모델을 이용한 화자분리 (0) | 2026.04.30 |
|---|---|
| [비교/검증-2] #4. Edge Agent AI 음성처리 : Sherpa-ONNX 실행 , 화자분리, 트러블슈팅정리 (1) | 2026.04.29 |
| [비교/검증-1] #3. Edge Agent AI 음성처리 : STT + 화자분리 경량엔진 3종 비교 + Pyannote 모델 (0) | 2026.04.29 |
| [Whisper.cpp] #2. Edge Agent AI 음성처리 : 한국어를 STT로 변환 비교(4종 비교) (0) | 2026.04.27 |
| [오디오추출] 안드로이드 환경에서 유튜브 특정 구간 오디오 추출하는방법 (0) | 2026.04.27 |
댓글