Backend: FastAPI + SQLAlchemy + SQLite Frontend: React + Vite + Ant Design (serif Anthropic theme) Media server: MediaMTX with edge node support Load balancing: round-robin / weighted / least-conn Multicast detection with automatic fallback Transcoding support via FFmpeg (configurable quality) hls.js player with line & quality switching Admin panel with password auth Windows compatible scripts
32 lines
1.4 KiB
Python
32 lines
1.4 KiB
Python
import uuid
|
|
from datetime import datetime
|
|
from sqlalchemy import String, Text, DateTime, Integer, Boolean, Enum
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
from database import Base
|
|
import enum
|
|
|
|
|
|
class StreamStatus(str, enum.Enum):
|
|
pending = "pending"
|
|
live = "live"
|
|
ended = "ended"
|
|
cancelled = "cancelled"
|
|
|
|
|
|
class Stream(Base):
|
|
__tablename__ = "streams"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
title: Mapped[str] = mapped_column(String(200), nullable=False)
|
|
description: Mapped[str | None] = mapped_column(Text, nullable=True)
|
|
cover_url: Mapped[str | None] = mapped_column(String(500), nullable=True)
|
|
stream_key: Mapped[str] = mapped_column(String(64), unique=True, default=lambda: uuid.uuid4().hex)
|
|
status: Mapped[StreamStatus] = mapped_column(Enum(StreamStatus), default=StreamStatus.pending)
|
|
scheduled_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
|
started_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
|
ended_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
|
assigned_nodes: Mapped[str | None] = mapped_column(Text, nullable=True)
|
|
multicast_enabled: Mapped[bool] = mapped_column(Boolean, default=False)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
|
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|