Home > OS >  path issues with FFMPEG Bash script to concat and encode across multiple subfolders
path issues with FFMPEG Bash script to concat and encode across multiple subfolders

Time:12-22

I'm trying to write a bash script for Terminal to compress a series of GoPro .MP4 videos from the SDcard directly into a smaller .MP4s on a local network server. The GoPro saves .MP4s in the 100GOPRO folder on the card. After filming, I will through that folder and manually put .MP4s from each game into subfolders within the 100GOPRO folder, named A1, A2, A3, etc.

Folder structure

/GoPro/DCIM/100GOPRO/
               -------/A1/
                       -----GX01xxx1.mp4
                       -----GX01xxx2.mp4
               -------/A2/
                       -----GX01xxx3.mp4
                       -----GX01xxx4.mp4
                       -----GX01xxx5.mp4
                       -----GX01xxx6.mp4

...etc

I would like then like to run a script from the 100GOPRO folder that will do these steps:

  1. Within each subfolder, auto-create a file.txt with the names of the subfolder's .MP4s in the format to concat the files (each line has "file 'GX01xxx3.mp4'")
  2. Pass that subfolder's file.txt as the input to ffmpeg to reencode and save to a network folder with the name A1.mp4 or A2.mp4
  3. Repeat for each subfolder and quit.

I'm getting hung up on the dynamic path to the subfolder's file.txt. My code just creates a file.txt in the 100GOPRO folder, and appends all the subfolder contents into that single long combined text file. The output then would create a correct first MP4, but second MP4 contains folder 1 and 2, then 3 contains 1, 2, and 3, etc.

Here's the script I ran:

#!/bin/bash
for f in A*/*.mp4 ; do
echo file \'$f\' >> list.txt ;
done && ffmpeg -f concat -safe 0 -i list.txt /Volume/Server/Videos/A$f.mp4 && rm list.txt

Clearly, failing in how that path for echo to save in the subfolder A*, how to call that subfolder's file.txt as the input for ffmpeg, and how to name the output after the folder.

Thanks for any help you can offer.

CodePudding user response:

Save the file list to a bash array, then loop over that. Tune the ffmpeg invocation to your liking.

#!/usr/bin/env bash

declare -a files=( $(find A* -type f -name \*.mp4) )

for file in "${files[*]}"; do
    ffmpeg -f concat -safe 0 -i "$file" "/Volume/Server/Videos/A${file}.mp4"
done

CodePudding user response:

Try this:

for d in $(find -maxdepth 1 -type d -name 'A*');
do
    printf "file '%s'\n" $d/*.mp4 > $d/inputs.txt
    ffmpeg -f concat -safe 0 -i $d/inputs.txt /Volume/Server/Videos/${d:2}.mp4
done

Explanation

  • The find looks for directories matching A*, and limited to subdirectories only 1-level deep
  • The glob $d/*.mp4 matches the mp4 files in each subdirectory, and the printf formats that into a list
  • the ffmpeg command is as you specified, the output filename uses the directory name, except it trims the first two characters (transforming ./A1 -> A1)

CodePudding user response:

You don't need intermediate files for this:

for d in A*; do
  printf '%s\n' "$d"/*.mp4 |
    ffmpeg -i concatf:/dev/stdin "/Volume/Server/Videos/${d#?}.mp4"
done
  • Related