feat: 모바일 반응형 + 변환 타임아웃 설정

This commit is contained in:
root
2026-04-23 02:33:57 +09:00
parent 248ac1deea
commit 4af1279a08
9 changed files with 967 additions and 1022 deletions

View File

@@ -1,7 +1,7 @@
import os
import httpx
from celery import Celery
from ocr_tasks import ocr_task # noqa: F401 — worker에 등록
from ocr_tasks import ocr_task # noqa: F401
REDIS_URL = os.getenv("REDIS_URL", "redis://redis:6379/0")
MODEL_SIZE = os.getenv("WHISPER_MODEL", "medium")
@@ -12,7 +12,10 @@ BEAM_SIZE = int(os.getenv("WHISPER_BEAM_SIZE", "5"))
INITIAL_PROMPT = os.getenv("WHISPER_INITIAL_PROMPT", "") or None
OUTPUT_DIR = os.getenv("OUTPUT_DIR", "/data/outputs")
OLLAMA_URL = os.getenv("OLLAMA_URL", "http://192.168.0.126:11434")
OLLAMA_TIMEOUT = int(os.getenv("OLLAMA_TIMEOUT", "180"))
OLLAMA_TIMEOUT = int(os.getenv("OLLAMA_TIMEOUT", "600"))
_cpu_threads_env = int(os.getenv("CPU_THREADS", "0"))
CPU_THREADS = _cpu_threads_env if _cpu_threads_env > 0 else None # None = auto
celery_app = Celery("whisper_tasks", broker=REDIS_URL, backend=REDIS_URL)
celery_app.conf.update(
@@ -29,15 +32,16 @@ def get_model():
global _model
if _model is None:
from faster_whisper import WhisperModel
print(f"[Whisper] 로딩: {MODEL_SIZE} / {DEVICE} / {COMPUTE_TYPE}")
_model = WhisperModel(MODEL_SIZE, device=DEVICE, compute_type=COMPUTE_TYPE)
kwargs = dict(device=DEVICE, compute_type=COMPUTE_TYPE)
if CPU_THREADS is not None:
kwargs["cpu_threads"] = CPU_THREADS
print(f"[Whisper] 로딩: {MODEL_SIZE} / {DEVICE} / {COMPUTE_TYPE} / threads={CPU_THREADS or 'auto'}")
_model = WhisperModel(MODEL_SIZE, **kwargs)
print("[Whisper] 로드 완료")
return _model
# ── Ollama 후처리 ─────────────────────────────────────────────
def _ollama_postprocess(text: str, model: str) -> str:
"""Whisper 결과를 Ollama로 후처리 (문장부호·맞춤법·자연스러운 문장)"""
if not model or not text.strip():
return text
prompt = (
@@ -49,33 +53,22 @@ def _ollama_postprocess(text: str, model: str) -> str:
try:
resp = httpx.post(
f"{OLLAMA_URL}/api/chat",
json={
"model": model,
"messages": [{"role": "user", "content": prompt}],
"stream": False,
"options": {"temperature": 0.1},
},
json={"model": model,
"messages": [{"role": "user", "content": prompt}],
"stream": False, "options": {"temperature": 0.1}},
timeout=float(OLLAMA_TIMEOUT),
)
resp.raise_for_status()
result = resp.json().get("message", {}).get("content", "").strip()
return result if result else text
except Exception as e:
print(f"[Ollama 후처리 실패] {e} — 원본 텍스트 사용")
print(f"[Ollama 후처리 실패] {e}")
return text
# ════════════════════════════════════════════════════════════════
# STT Celery Task
# ════════════════════════════════════════════════════════════════
@celery_app.task(bind=True, name="tasks.transcribe_task", queue="stt")
def transcribe_task(
self,
file_id: str,
audio_path: str,
use_ollama: bool = False,
ollama_model: str = "",
):
def transcribe_task(self, file_id: str, audio_path: str,
use_ollama: bool = False, ollama_model: str = ""):
self.update_state(state="PROGRESS", meta={"progress": 5, "message": "모델 준비 중..."})
try:
model = get_model()
@@ -97,8 +90,8 @@ def transcribe_task(
duration = info.duration
for seg in segments_gen:
segments.append({"start": round(seg.start,2),
"end": round(seg.end,2),
segments.append({"start": round(seg.start, 2),
"end": round(seg.end, 2),
"text": seg.text.strip()})
parts.append(seg.text.strip())
if duration > 0:
@@ -112,7 +105,6 @@ def transcribe_task(
raw_text = "\n".join(parts)
full_text = raw_text
# Ollama 후처리
if use_ollama and ollama_model:
self.update_state(state="PROGRESS",
meta={"progress": 85,