pmootr's picture
Add URL/YouTube ingestion, "add-a-sample" workflow, and architecture doc
aa5e3cc
Raw
History Blame Contribute Delete
1.65 kB
"""Small, dependency-free helpers shared across modules."""
from __future__ import annotations
import re
from typing import Iterable, List
def slugify(text: str, fallback: str = "video", max_len: int = 60) -> str:
"""Filesystem-safe, lowercase slug (e.g. for a video id derived from a URL)."""
text = (text or "").strip().lower()
slug = re.sub(r"[^a-z0-9]+", "_", text).strip("_")
slug = slug[:max_len].strip("_")
return slug or fallback
def format_timestamp(seconds: float) -> str:
"""Return an ``HH:MM:SS`` label for a number of seconds."""
seconds = max(0, int(round(seconds)))
h, rem = divmod(seconds, 3600)
m, s = divmod(rem, 60)
return f"{h:02d}:{m:02d}:{s:02d}"
def extract_keywords(text: str, domain_terms: Iterable[str]) -> List[str]:
"""Return the domain terms that appear in ``text`` (case-insensitive).
Multi-word terms are matched as substrings, which is robust to Thai-English
code-switching where English keywords are embedded inside Thai sentences.
The result preserves the order in which terms appear in ``domain_terms`` and
contains no duplicates.
"""
if not text:
return []
lowered = text.lower()
found: List[str] = []
for term in domain_terms:
t = term.lower().strip()
if t and t in lowered and term not in found:
found.append(term)
return found
def contains_any(text: str, phrases: Iterable[str]) -> List[str]:
"""Return every phrase from ``phrases`` that occurs in ``text``."""
if not text:
return []
lowered = text.lower()
return [p for p in phrases if p.lower() in lowered]