Files
personal_development/video_transcription/ai_transcriber_v2/tracker.py
T

102 lines
3.1 KiB
Python

import logging
import os
import socket
from datetime import datetime
from sqlalchemy import create_engine, Column, Integer, String, DateTime, Enum, Text
from sqlalchemy.orm import declarative_base, sessionmaker
import enum
# Get Hostname for namespacing
HOSTNAME = socket.gethostname()
# Setup Logging
log_dir = "logs"
os.makedirs(log_dir, exist_ok=True)
log_file = os.path.join(log_dir, f"transcriber_{HOSTNAME}_{datetime.now().strftime('%Y%m%d')}.log")
# Create formatters
log_formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
# File Handler (Full Detail)
file_handler = logging.FileHandler(log_file)
file_handler.setFormatter(log_formatter)
file_handler.setLevel(logging.INFO)
# Stream Handler (Quiet Detail for Terminal)
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(log_formatter)
stream_handler.setLevel(logging.WARNING) # Only warnings/errors to terminal
logging.basicConfig(
level=logging.INFO,
handlers=[file_handler, stream_handler]
)
logger = logging.getLogger(__name__)
# Database Setup
Base = declarative_base()
DB_FILE = f"job_history_{HOSTNAME}.db"
class JobStatus(enum.Enum):
PENDING = "pending"
PROCESSING = "processing"
COMPLETED = "completed"
FAILED = "failed"
class Job(Base):
__tablename__ = 'jobs'
id = Column(Integer, primary_key=True)
file_path = Column(String, unique=True, nullable=False)
status = Column(Enum(JobStatus), default=JobStatus.PENDING)
error_message = Column(Text, nullable=True)
last_updated = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Track progress of individual steps
step_extract = Column(String, default="pending") # pending, done, failed
step_transcribe = Column(String, default="pending")
step_translate = Column(String, default="pending")
step_embed = Column(String, default="pending")
engine = create_engine(f'sqlite:///{DB_FILE}')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
def get_job(file_path):
session = Session()
job = session.query(Job).filter_by(file_path=file_path).first()
if not job:
job = Job(file_path=file_path)
session.add(job)
session.commit()
session.refresh(job) # Ensure we have the ID and defaults
# Detach from session so we can use it after session.close()
session.expunge(job)
session.close()
return job
def update_job_status(file_path, status, error=None):
session = Session()
job = session.query(Job).filter_by(file_path=file_path).first()
if job:
job.status = status
if error:
job.error_message = str(error)
session.commit()
session.close()
def update_step(file_path, step_name, status):
session = Session()
job = session.query(Job).filter_by(file_path=file_path).first()
if job:
setattr(job, step_name, status)
session.commit()
session.close()
def get_failed_jobs():
session = Session()
jobs = session.query(Job).filter_by(status=JobStatus.FAILED).all()
session.close()
return [j.file_path for j in jobs]