Skip to content

Instantly share code, notes, and snippets.

@ariunbayar
Created March 26, 2025 18:49
Show Gist options
  • Select an option

  • Save ariunbayar/163dfd98400baa00beb12b1a13bcc3a6 to your computer and use it in GitHub Desktop.

Select an option

Save ariunbayar/163dfd98400baa00beb12b1a13bcc3a6 to your computer and use it in GitHub Desktop.
Joins same day video by date. Original files are archived into a `processed` dir.
#!/bin/bash
# --- Configuration ---
# Video encoding options (same as your example)
VCODEC="libx264"
CRF="23"
PRESET="medium"
ACODEC="aac"
ABITRATE="192k"
OUTPUT_EXT="mp4" # Output container format extension
# Directory to move processed source files
PROCESSED_DIR="processed"
# --- Script Logic ---
# Create the target directory for processed files if it doesn't exist
mkdir -p "$PROCESSED_DIR"
if [ ! -d "$PROCESSED_DIR" ]; then
echo "Error: Could not create directory '$PROCESSED_DIR'."
exit 1
fi
echo "Scanning for unique dates in MPG filenames..."
# Find unique dates (YYYY-MM-DD) from filenames matching the pattern
# Using find for safety, extracting date with cut, sorting uniquely
# Using process substitution and mapfile (or readarray) to store dates.
mapfile -t unique_dates < <(find . -maxdepth 1 -name '????-??-??_????_M*.MPG' -printf '%f\n' | cut -c1-10 | sort -u)
# Check if any dates were found
if [ ${#unique_dates[@]} -eq 0 ]; then
echo "No MPG files found matching the pattern YYYY-MM-DD_HHMM_M*.MPG in the current directory."
exit 0
fi
echo "Found dates to process: ${unique_dates[*]}"
echo "Starting processing..."
echo "--------------------"
# Loop through each unique date
for date in "${unique_dates[@]}"; do
echo "Processing date: $date"
# Find and sort all .MPG files for the current date
# Using find for safety and storing results in an array using mapfile
mapfile -t files_for_date < <(find . -maxdepth 1 -name "${date}_????_M*.MPG" -printf '%f\n' | sort)
# Check if files were actually found for this date (should always be true here, but good practice)
if [ ${#files_for_date[@]} -eq 0 ]; then
echo " Warning: No files found for date $date during processing loop (unexpected)."
continue
fi
echo " Files found for $date: ${files_for_date[*]}"
# Construct the ffmpeg concat input string (e.g., file1.MPG|file2.MPG)
# Using IFS and array expansion for safe joining
input_concat_string=$(IFS='|'; echo "${files_for_date[*]}")
# Determine the output filename: Use the date and the timestamp from the *first* sorted file
# Removes the _M* part and changes extension, e.g., 2014-09-08_0907.mp4
first_file_basename="${files_for_date[0]}"
# Using sed to replace the last underscore segment and extension
output_name=$(echo "$first_file_basename" | sed "s/_[^_]*\.MPG$/.${OUTPUT_EXT}/")
echo " Output file will be: $output_name"
# Check if output file already exists to prevent accidental overwrite or re-processing
if [ -f "$output_name" ]; then
echo " SKIPPING: Output file '$output_name' already exists."
# Optional: Decide if you want to move source files even if output exists
# echo " Moving source files for skipped date..."
# for file in "${files_for_date[@]}"; do mv -- "$file" "$PROCESSED_DIR/"; done
echo "--------------------"
continue
fi
# Prepare the ffmpeg command arguments in an array for robustness
ffmpeg_cmd=(
ffmpeg
-i "concat:$input_concat_string"
-c:v "$VCODEC"
-crf "$CRF"
-preset "$PRESET"
-c:a "$ACODEC"
-b:a "$ABITRATE"
# Optional: Add -map 0 if you encounter channel mapping issues
"$output_name"
)
echo " Executing FFmpeg..."
# Use "${ffmpeg_cmd[@]}" to correctly handle arguments with spaces if any
if "${ffmpeg_cmd[@]}"; then
echo " SUCCESS: FFmpeg finished for $date."
echo " Moving original files to '$PROCESSED_DIR/'..."
# Move source files to the 'processed' directory *only on success*
for file in "${files_for_date[@]}"; do
# Use -- to handle filenames that might start with a dash
mv -- "$file" "$PROCESSED_DIR/"
done
echo " Moved ${#files_for_date[@]} files for $date."
else
echo " FAILURE: FFmpeg failed for $date. Original files were NOT moved."
# Optional: You might want to delete the potentially incomplete output file on failure
# rm -f "$output_name"
fi
echo "--------------------"
done
echo "All processing finished."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment