#!/bin/bash echo "Transcoding service started..." # Configuration QUEUE_DIR="/var/www/html/download/queue" READY_DIR="/var/www/html/download/ready" SETTINGS_FILE="/var/www/html/settings/settings.json" LOG_FILE="/var/log/convert.log" LOGO_FILE="/var/www/html/settings/logo.png" # Create directories if they don't exist mkdir -p "$QUEUE_DIR" mkdir -p "$READY_DIR" # Load settings from JSON file load_settings() { VIDEO_FORMAT=$(jq -r '.video_format' "$SETTINGS_FILE") AUDIO_FORMAT=$(jq -r '.audio_format' "$SETTINGS_FILE") VIDEO_BITRATE=$(jq -r '.video_bitrate' "$SETTINGS_FILE") AUDIO_BITRATE=$(jq -r '.audio_bitrate' "$SETTINGS_FILE") RESOLUTION=$(jq -r '.resolution' "$SETTINGS_FILE") FRAME_RATE=$(jq -r '.frame_rate' "$SETTINGS_FILE") GOP=$(jq -r '.gop' "$SETTINGS_FILE") } # Function to sanitize filename sanitize_filename() { local filename="$1" # Remove special characters, keep only a-z, A-Z, 0-9, and . local sanitized=$(echo "$filename" | sed 's/[^a-zA-Z0-9.]*//g') # If filename starts with number, add prefix if [[ "$sanitized" =~ ^[0-9] ]]; then sanitized="dev_${sanitized}" fi # If filename is empty after sanitization, use timestamp if [[ -z "$sanitized" ]]; then sanitized="dev_$(date +%s)" fi echo "$sanitized" } # Function to get video resolution get_video_resolution() { local input_file="$1" ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 "$input_file" } # Function to calculate logo size based on video resolution calculate_logo_size() { local video_width="$1" local video_height="$2" # Calculate 10% of video width/height for logo size local logo_width=$((video_width / 10)) local logo_height=$((video_height / 10)) # Ensure minimum size of 64x64 if [ "$logo_width" -lt 64 ]; then logo_width=64; fi if [ "$logo_height" -lt 64 ]; then logo_height=64; fi # Ensure maximum size of 128x128 if [ "$logo_width" -gt 128 ]; then logo_width=128; fi if [ "$logo_height" -gt 128 ]; then logo_height=128; fi echo "${logo_width}x${logo_height}" } # Main processing loop while true; do # Load settings at start of each loop load_settings # Find all files in queue directory for file in "$QUEUE_DIR"/*; do # Skip if no files found [ -f "$file" ] || continue # Get original filename original_name=$(basename "$file") # Sanitize filename sanitized_name=$(sanitize_filename "$original_name") # Add .ts extension sanitized_name="${sanitized_name}.ts" # Set output path output_file="$READY_DIR/$sanitized_name" # Check if logo file exists if [ -f "$LOGO_FILE" ]; then # Get video resolution video_res=$(get_video_resolution "$file") video_width=$(echo "$video_res" | cut -d'x' -f1) video_height=$(echo "$video_res" | cut -d'x' -f2) # Calculate logo size logo_size=$(calculate_logo_size "$video_width" "$video_height") # STB compatible encoding based on video format if [ "$VIDEO_FORMAT" = "mpeg2video" ]; then # MPEG2 settings for STB compatibility ffmpeg \ -i "$file" \ -i "$LOGO_FILE" \ -filter_complex "\ [0:v]scale=${RESOLUTION}[v];\ [1:v]scale=${logo_size}[logo];\ [v][logo]overlay=W-w-20:20" \ -c:v mpeg2video \ -b:v "$VIDEO_BITRATE" \ -bt "$VIDEO_BITRATE" \ -maxrate "$VIDEO_BITRATE" \ -bufsize "$VIDEO_BITRATE" \ -flags +global_header \ -profile:v 2 \ -level:v 4 \ -c:a "$AUDIO_FORMAT" \ -b:a "$AUDIO_BITRATE" \ -ab "$AUDIO_BITRATE" \ -r "$FRAME_RATE" \ -g "$GOP" \ -f mpegts "$output_file" \ 2>>"$LOG_FILE" elif [ "$VIDEO_FORMAT" = "libx264" ]; then # H.264 settings for STB compatibility ffmpeg \ -i "$file" \ -i "$LOGO_FILE" \ -filter_complex "\ [0:v]scale=${RESOLUTION}[v];\ [1:v]scale=${logo_size}[logo];\ [v][logo]overlay=W-w-20:20" \ -c:v libx264 \ -b:v "$VIDEO_BITRATE" \ -bt "$VIDEO_BITRATE" \ -maxrate "$VIDEO_BITRATE" \ -bufsize "$VIDEO_BITRATE" \ -preset fast \ -profile:v baseline \ -level 3.0 \ -flags +global_header \ -c:a "$AUDIO_FORMAT" \ -b:a "$AUDIO_BITRATE" \ -ab "$AUDIO_BITRATE" \ -r "$FRAME_RATE" \ -g "$GOP" \ -f mpegts "$output_file" \ 2>>"$LOG_FILE" elif [ "$VIDEO_FORMAT" = "libx265" ]; then # H.265 settings for STB compatibility ffmpeg \ -i "$file" \ -i "$LOGO_FILE" \ -filter_complex "\ [0:v]scale=${RESOLUTION}[v];\ [1:v]scale=${logo_size}[logo];\ [v][logo]overlay=W-w-20:20" \ -c:v libx265 \ -b:v "$VIDEO_BITRATE" \ -bt "$VIDEO_BITRATE" \ -maxrate "$VIDEO_BITRATE" \ -bufsize "$VIDEO_BITRATE" \ -preset fast \ -profile:v main \ -level 3.0 \ -flags +global_header \ -c:a "$AUDIO_FORMAT" \ -b:a "$AUDIO_BITRATE" \ -ab "$AUDIO_BITRATE" \ -r "$FRAME_RATE" \ -g "$GOP" \ -f mpegts "$output_file" \ 2>>"$LOG_FILE" else # Default fallback to MPEG2 ffmpeg \ -i "$file" \ -i "$LOGO_FILE" \ -filter_complex "\ [0:v]scale=${RESOLUTION}[v];\ [1:v]scale=${logo_size}[logo];\ [v][logo]overlay=W-w-20:20" \ -c:v mpeg2video \ -b:v "$VIDEO_BITRATE" \ -bt "$VIDEO_BITRATE" \ -maxrate "$VIDEO_BITRATE" \ -bufsize "$VIDEO_BITRATE" \ -flags +global_header \ -profile:v 2 \ -level:v 4 \ -c:a "$AUDIO_FORMAT" \ -b:a "$AUDIO_BITRATE" \ -ab "$AUDIO_BITRATE" \ -r "$FRAME_RATE" \ -g "$GOP" \ -f mpegts "$output_file" \ 2>>"$LOG_FILE" fi # Check if conversion was successful if [ $? -eq 0 ]; then rm "$file" echo "$(date): Successfully converted $original_name to $sanitized_name" >> "$LOG_FILE" else # If conversion failed, log error echo "$(date): Failed to convert $original_name" >> "$LOG_FILE" fi else # STB compatible encoding without logo if [ "$VIDEO_FORMAT" = "mpeg2video" ]; then # MPEG2 settings for STB compatibility ffmpeg \ -i "$file" \ -c:v mpeg2video \ -b:v "$VIDEO_BITRATE" \ -bt "$VIDEO_BITRATE" \ -maxrate "$VIDEO_BITRATE" \ -bufsize "$VIDEO_BITRATE" \ -flags +global_header \ -profile:v 2 \ -level:v 4 \ -c:a "$AUDIO_FORMAT" \ -b:a "$AUDIO_BITRATE" \ -ab "$AUDIO_BITRATE" \ -s "$RESOLUTION" \ -r "$FRAME_RATE" \ -g "$GOP" \ -f mpegts "$output_file" \ 2>>"$LOG_FILE" elif [ "$VIDEO_FORMAT" = "libx264" ]; then # H.264 settings for STB compatibility ffmpeg \ -i "$file" \ -c:v libx264 \ -b:v "$VIDEO_BITRATE" \ -bt "$VIDEO_BITRATE" \ -maxrate "$VIDEO_BITRATE" \ -bufsize "$VIDEO_BITRATE" \ -preset fast \ -profile:v baseline \ -level 3.0 \ -flags +global_header \ -c:a "$AUDIO_FORMAT" \ -b:a "$AUDIO_BITRATE" \ -ab "$AUDIO_BITRATE" \ -s "$RESOLUTION" \ -r "$FRAME_RATE" \ -g "$GOP" \ -f mpegts "$output_file" \ 2>>"$LOG_FILE" elif [ "$VIDEO_FORMAT" = "libx265" ]; then # H.265 settings for STB compatibility ffmpeg \ -i "$file" \ -c:v libx265 \ -b:v "$VIDEO_BITRATE" \ -bt "$VIDEO_BITRATE" \ -maxrate "$VIDEO_BITRATE" \ -bufsize "$VIDEO_BITRATE" \ -preset fast \ -profile:v main \ -level 3.0 \ -flags +global_header \ -c:a "$AUDIO_FORMAT" \ -b:a "$AUDIO_BITRATE" \ -ab "$AUDIO_BITRATE" \ -s "$RESOLUTION" \ -r "$FRAME_RATE" \ -g "$GOP" \ -f mpegts "$output_file" \ 2>>"$LOG_FILE" else # Default fallback to MPEG2 ffmpeg \ -i "$file" \ -c:v mpeg2video \ -b:v "$VIDEO_BITRATE" \ -bt "$VIDEO_BITRATE" \ -maxrate "$VIDEO_BITRATE" \ -bufsize "$VIDEO_BITRATE" \ -flags +global_header \ -profile:v 2 \ -level:v 4 \ -c:a "$AUDIO_FORMAT" \ -b:a "$AUDIO_BITRATE" \ -ab "$AUDIO_BITRATE" \ -s "$RESOLUTION" \ -r "$FRAME_RATE" \ -g "$GOP" \ -f mpegts "$output_file" \ 2>>"$LOG_FILE" fi # Check if conversion was successful if [ $? -eq 0 ]; then rm "$file" echo "$(date): Successfully converted $original_name to $sanitized_name" >> "$LOG_FILE" else # If conversion failed, log error echo "$(date): Failed to convert $original_name" >> "$LOG_FILE" fi fi done # Wait before checking for new files sleep 60 done