Automated Archiving Service
Go to file
2025-09-08 12:58:36 -04:00
src Clean up architecture and remove unused code 2025-09-08 12:30:57 -04:00
tests Major refactoring: Event-driven livestream archiver 2025-09-06 18:27:59 -04:00
.env.example Security improvements and architecture cleanup 2025-09-08 12:09:58 -04:00
.gitignore Add documentation and configuration templates 2025-08-16 19:05:59 -04:00
Cargo.lock Security improvements and architecture cleanup 2025-09-08 12:09:58 -04:00
Cargo.toml Major refactoring: Event-driven livestream archiver 2025-09-06 18:27:59 -04:00
deploy.sh.example Add documentation and configuration templates 2025-08-16 19:05:59 -04:00
LICENSE Add documentation and configuration templates 2025-08-16 19:05:59 -04:00
livestream-archiver.service.example Make paths configurable via environment variables 2025-08-16 19:09:21 -04:00
README.md Update README.md 2025-09-08 12:58:36 -04:00

Livestream Archiver

An event-driven Rust service that automatically detects livestream recordings, converts them for efficient storage, and syncs originals to PC for editing. Uses the shared video_processing crate for optimal performance.

Features

  • Event-driven file detection - No polling, instant response to new files
  • PC sync for editing - Syncs original files to Mac/PC for post-production
  • AV1 video conversion with Intel QSV hardware acceleration
  • Smart program naming - Detects Divine Worship vs Afternoon Program
  • File stability checking - Ensures files are fully written before processing
  • Date-based organization - Jellyfin-compatible directory structure
  • NFO file generation - Complete media server metadata
  • Efficient resource usage - Only processes when files appear

Prerequisites

  • Rust toolchain (latest stable)
  • ffmpeg with Intel QSV support
  • rsync for file synchronization
  • SSH key authentication for passwordless rsync to PC
  • Intel Media SDK (for QSV acceleration)

Installation

Building from Source

# Clone the repository
git clone <repository-url>
cd livestream-archiver

# Build release binary
cargo build --release

# Binary will be at target/release/livestream_archiver

Configuration

Create a .env file based on .env.example:

cp .env.example .env
nano .env

Required Environment Variables

# Directory paths (REQUIRED)
INPUT_DIR=/home/rockvilleav/.rtsda/livestreams
OUTPUT_DIR=/media/archive/jellyfin/livestreams

# PC sync target for editing (REQUIRED)
PC_SYNC_TARGET=user@macbook.local:~/rtsda/livestreams/

# Program naming
DIVINE_WORSHIP_NAME=Divine Worship Service - RTSDA
AFTERNOON_PROGRAM_NAME=Afternoon Program - RTSDA

# FFmpeg Configuration
FFMPEG_BINARY=ffmpeg
VIDEO_CODEC=av1_qsv              # AV1 with Intel QSV
HW_ACCEL=qsv
HW_DEVICE=qsv=hw
FFMPEG_PRESET=4
VIDEO_BITRATE=6M
MAX_BITRATE=12M
BUFFER_SIZE=24M
AUDIO_CODEC=copy                 # Preserve original audio
AUDIO_BITRATE=192k

# File Stability Settings
STABILITY_CHECK_INTERVAL=2       # seconds between stability checks
STABILITY_REQUIRED_CHECKS=15     # consecutive stable checks required
MAX_STABILITY_WAIT_HOURS=4       # maximum time to wait for stability

# Directory Settings
CREATE_YEAR_MONTH_DIRS=true      # organize by date
PRESERVE_ORIGINAL_FILES=true     # keep originals after conversion

# NFO Settings
SHOW_TITLE=LiveStreams
CREATE_NFO_FILES=true            # or false to disable

Expected File Format

Livestream files should follow OBS naming convention:

YYYY-MM-DD_HH-MM-SS.mp4

Examples:

  • 2024-12-25_10-30-00.mp4 → Divine Worship Service (Christmas 2024)
  • 2024-12-25_14-00-00.mp4 → Afternoon Program (Christmas 2024)

The service automatically detects service type based on file timing and existing files.

Running as a System Service

Create a systemd service file at /etc/systemd/system/livestream-archiver.service:

[Unit]
Description=Livestream Archive Service
After=network.target media-archive.mount

[Service]
Type=simple
User=rockvilleav
Group=rockvilleav
ExecStart=/usr/local/bin/livestream_archiver
WorkingDirectory=/home/rockvilleav/livestream-archiver

# Load environment variables from .env file
EnvironmentFile=/home/rockvilleav/livestream-archiver/.env

# Environment variables for home directory access
Environment=HOME=/home/rockvilleav
Environment=USER=rockvilleav
Environment=XDG_RUNTIME_DIR=/run/user/1000

# Intel Media Stack environment
Environment=LIBVA_DRIVER_NAME=iHD
Environment=LIBVA_DRIVERS_PATH=/opt/intel/media/lib64
Environment=LD_LIBRARY_PATH=/opt/intel/media/lib64
Environment=LIBVA_DRIVER_PATH=/opt/intel/media/lib64
Environment=DISPLAY=:0

# Restart settings
Restart=always
RestartSec=10

# Make sure service has access to needed directories
RequiresMountsFor=/media/archive

[Install]
WantedBy=multi-user.target

Enable and start the service:

sudo systemctl enable livestream-archiver
sudo systemctl start livestream-archiver
sudo systemctl status livestream-archiver

View logs:

sudo journalctl -u livestream-archiver -f

How It Works

  1. Event Detection: Uses inotify to instantly detect new MP4 files (no polling!)
  2. File Stability: Waits for OBS to finish writing the file completely
  3. PC Sync: Immediately syncs the original file to Mac/PC for editing via rsync
  4. AV1 Conversion: Converts to efficient AV1 format for long-term storage
  5. Smart Naming: Determines Divine Worship vs Afternoon Program automatically
  6. Organization: Places files in date-based directories for Jellyfin
  7. NFO Generation: Creates metadata files for media server compatibility
  8. Preservation: Keeps original files on server for backup

Directory Structure

Output files are organized by date:

/media/archive/jellyfin/livestreams/
├── 2024/
│   ├── 12-December/
│   │   ├── Divine Worship Service - RTSDA (December 25 2024).mp4
│   │   ├── Divine Worship Service - RTSDA (December 25 2024).nfo
│   │   ├── Afternoon Program - RTSDA (December 25 2024).mp4
│   │   ├── Afternoon Program - RTSDA (December 25 2024).nfo
│   │   └── ...
│   └── 01-January/
└── 2025/

PC sync creates:

~/rtsda/livestreams/
├── 2024-12-25_10-30-00.mp4  # Original for editing
├── 2024-12-25_14-00-00.mp4  # Original for editing
└── ...

Architecture

This service uses a clean, event-driven architecture:

  • Event Detection: Uses Linux inotify for instant file detection (no polling)
  • File Stability: Proper completion detection before processing
  • Shared Logic: Uses video_processing crate for common functionality
  • Dual Output: Converted files for storage + original sync for editing
  • Resource Efficient: Only uses resources when files actually appear

Video Conversion Details

Default settings (configurable via .env):

  • Video Codec: AV1 with Intel QSV hardware acceleration
  • Audio Codec: Copy (preserves original quality)
  • Hardware Acceleration: Intel Quick Sync Video
  • Video Bitrate: 6Mbps (efficient for streaming)
  • Max Bitrate: 12Mbps (for complex scenes)

Troubleshooting

Service fails to start

# Check if .env file exists and has correct paths
ls -la /home/rockvilleav/livestream-archiver/.env

# Verify directories exist and are accessible
ls -la /home/rockvilleav/.rtsda/livestreams
ls -la /media/archive/jellyfin/livestreams

# Check systemd service file
sudo systemctl cat livestream-archiver

PC sync failures

# Test SSH connection manually
ssh user@macbook.local

# Test rsync manually
rsync -avz /test/file user@macbook.local:~/rtsda/livestreams/

# Check SSH key authentication
ssh-copy-id user@macbook.local

FFmpeg/QSV issues

# Test FFmpeg with Intel QSV
ffmpeg -encoders | grep av1_qsv
ffmpeg -hwaccels | grep qsv

# Check Intel Media SDK
vainfo

Files not being detected

# Check logs for file events
sudo journalctl -u livestream-archiver -f

# Test file detection manually
touch /home/rockvilleav/.rtsda/livestreams/test-2024-01-01_10-00-00.mp4

Disk space issues

# Service checks for 5GB minimum free space
df -h /media/archive/jellyfin/livestreams

Development

Running Tests

cargo test

Running Manually

# Set environment variables
export INPUT_DIR="/path/to/input"
export OUTPUT_DIR="/path/to/output"
export PC_SYNC_TARGET="user@host:~/path/"

# Run with debug logging
RUST_LOG=debug cargo run

License

This project is licensed under the MIT License - see the LICENSE file for details.

Contributing

Contributions are welcome! This service is part of a larger church media processing system.