Skip to content

Video Processing

Chatto can transcode uploaded videos into multiple quality variants for adaptive playback. When a user uploads a video, the server generates optimized versions (e.g. 720p, 480p) and a thumbnail, then serves them through a built-in video player.

Video processing requires ffmpeg and ffprobe to be installed on the server. The official Chatto Docker image includes both.

If you’re running Chatto outside Docker, install ffmpeg through your system’s package manager:

Terminal window
# Debian/Ubuntu
apt install ffmpeg
# macOS (Homebrew)
brew install ffmpeg
# Alpine
apk add ffmpeg

Add the following to your chatto.toml:

[video]
enabled = true

Or set the environment variable:

Terminal window
CHATTO_VIDEO_ENABLED=true

That’s it. Chatto will auto-detect ffmpeg and ffprobe from your PATH.

All settings live under the [video] section in chatto.toml. See the Environment Variables reference for the full list.

SettingDefaultDescription
enabledfalseEnable video processing
ffmpeg_pathauto-detectPath to ffmpeg binary
ffprobe_pathauto-detectPath to ffprobe binary
max_concurrent2Max concurrent transcoding jobs
max_upload_size100 MBMax upload size for video files
temp_dirsystem tempDirectory for temporary transcoding files

Each transcoding job uses significant CPU. The default of 2 concurrent jobs is conservative. On a dedicated server with more cores, you can increase this:

[video]
enabled = true
max_concurrent = 4

If ffmpeg and ffprobe aren’t in your PATH, specify their locations explicitly:

[video]
enabled = true
ffmpeg_path = "/usr/local/bin/ffmpeg"
ffprobe_path = "/usr/local/bin/ffprobe"
  1. A user uploads a video through the chat composer
  2. The original file is stored immediately and the message is posted
  3. The video appears with a “Processing…” indicator
  4. In the background, Chatto transcodes the video into multiple quality variants and generates a thumbnail
  5. Once processing completes, the player switches to adaptive playback with quality selection

If processing fails (e.g. corrupt file, unsupported codec), the user sees an error message and can try uploading again.

Video transcoding generates multiple output files per upload (quality variants + thumbnail). If you expect significant video usage, consider:

  • Using S3 storage for assets (core.assets.storage_backend = "s3") to avoid filling up NATS JetStream storage
  • Providing a fast temp directory with enough free space for in-progress transcoding jobs