Skip to content

Architecture

VideoCMS v0.1.0 (Beta) uses a unified architecture where the backend (API) and frontend (Panel) are served by a single service.

High-Level Overview

Service Components

The Transcoding Pipeline

VideoCMS uses a prioritized queue system to handle video processing. This ensures that essential components (like audio and subtitles) are ready before the heavy video encoding begins.

1. Upload & Assembly

  1. Resumable Upload: The frontend uploads through the embedded tus endpoint at /api/uploads. Browser refreshes and network interruptions can resume within the upload retention window.
  2. Finalize: After tus reports completion, VideoCMS finalizes the upload and moves the completed raw file from ./videos/uploads/tus/ to ./videos/uploads/{uuid}.tmp.
  3. Validation: ffprobe checks the file for valid video streams, resolution (50px - 8000px), and duration.
  4. Hashing: A SHA256 hash is generated to detect duplicate files. If a duplicate is found, the new upload acts as a "symlink" to the existing file (Database-level cloning), saving storage space.
  5. Registration: The valid file is registered in the database and queued for media processing.

2. The Worker Loop

The backend runs a background service (services/Encoder.go) that wakes up every 10 seconds to look for pending tasks. It processes them in this specific order:

  1. Subtitles (Priority 1):

    • Extracts embedded subtitles from the source file.
    • Converts them to .vtt (WebVTT) or .ass (Advanced Substation Alpha).
    • Note: Image-based subtitles (PGS) are sent to an external plugin for OCR if enabled.
  2. Audio (Priority 2):

    • Extracts audio tracks.
    • Converts them to HLS Segmented Audio (.m3u8 + .ts segments).
    • Stereo, 5.1, and 7.1 layouts are supported.
  3. Video / Qualities (Priority 3):

    • Transcodes the video into the resolutions defined in your settings (1080p, 720p, etc.).
    • Uses HLS (HTTP Live Streaming) with libx264.
    • Settings: 4-second segments, Closed GOP, YUV420p.

Storage Structure

VideoCMS uses a flat-folder structure where the Video UUID is the root folder for that asset.

./videos Directory

This is the main storage volume. You should never manually delete files here unless you know what you are doing, as it will break database references.

text
./videos/
├── uploads/                  # Temporary staging area for raw uploads
│   ├── tus/                  # Active tus upload resources and metadata
│   └── {file_uuid}.tmp       # Finalized raw video before/while import

└── qualitys/                 # Permanent storage for processed media
    └── {video_uuid}/         # The processed video folder (HLS assets)
        ├── {quality_name}/   # e.g., "1080p", "720p"
        │   ├── index.m3u8    # Playlist for this specific quality
        │   ├── segment0.ts   # Video segment 0
        │   └── segment1.ts   # Video segment 1...

        ├── {audio_uuid}/     # Audio Track 1
        │   ├── index.m3u8
        │   └── segment0.ts

        └── {subtitle_uuid}/  # Subtitle Track 1
            └── subtitle.vtt  # The subtitle file

Where is master.m3u8?

You won't find a master.m3u8 file on the disk. VideoCMS generates the Master Playlist dynamically on the fly when a user requests it.

This allows the server to:

  1. Instantly enable/disable specific qualities without re-writing files.
  2. Serve different audio tracks based on user language preferences.
  3. Keep media URLs tokenless while the Go server verifies the HttpOnly media cookie set by the player page.

Database Flow

VideoCMS uses SQLite in WAL (Write-Ahead Logging) mode.

  • files table: Stores metadata about the physical file (Hash, Path, Duration).
  • links table: Represents the "User's View" of a file. Multiple users can have different links pointing to the same file (Deduplication).
  • qualities, audios, subtitles: Store the status (Ready, Encoding, Failed) of each asset.

Scaling Implications

  • CPU: The "Worker Loop" is CPU-intensive. Since it runs inside the API binary, scaling the API horizontally (multiple replicas) requires a shared filesystem (NFS) for ./videos and a shared database, which SQLite does not support well across networks.
  • Storage: Since the structure is flat file-based, you can easily mount ./videos to a large HDD array or use rclone (see Cookbooks) to mount S3 buckets.

Released under the AGPL-3.0 License.