2

I have many hundreds of videos, each a few minutes long and to which was appended an intro and outro sequence that I would like to automatically remove. There is always an all-black frame immediately following the intro sequence and immediately preceding the outro sequence.

Is there a way to batch (for all videos in a folder, macOS High Sierra) detect and remove all the material preceding the first black frame in a video? (I have the same question for removing the outro sequence, if a workable solution exists.)

Thank you.

1 Answer 1

2

You can try using ffprobe scene detection tool to find the black frame time, then use ffmpeg to seek and trim.

I'm not very good at scripting, but here is something you can try. It is very important that the black frame be only a single frame for this to work! Also, ffprobe's scene tool is very picky about file paths, so make sure there are no spaces or special characters in the filename or file path of any of the videos you need to edit.

Copy and paste the following code into a bash or command script file. I'll walk through each step to explain what's happening after.

#!/bin/bash

echo "Enter Source Folder"

read input

cd "$input"

mkdir -p "$input"/output

dir="$input"/output

for video in *; do

if [[ -f "$video" ]]; then

filename="${video%.*}"
extension="${video##*.}"

mkdir "$dir"/"$filename"

dest="$dir"/"$filename"

ffprobe -show_frames -of compact=p=0 -f lavfi "movie="$video",select=gt(scene\,0.9)" -show_entries frame=best_effort_timestamp_time > tmp.txt

sed -e 's/.*best_effort_timestamp_time=\(.*\)|tag:lavfi.scene_score.*/\1/' tmp.txt > chapter.txt
rm tmp.txt

file=chapter.txt
while read line
do
    time+=($line)   
done <"$file"

ffmpeg -i "$video" -ss "${time[0]}" -to "${time[1]}" "$dest"/middle-"$filename"."$extension"

rm chapter.txt

fi

done

Breakdown

Determine the folder that contains the videos you want to trim and set it as the working directory.

#!/bin/bash
echo "Enter Source Folder"
read input
cd "$input"

Make output directory

mkdir -p "$input"/output
dir="$input"/output

For each file in the folder do this:

  1. make sure it's a file and not a folder
  2. save the filename and extension as a variable
  3. create a new output directory for each video

    for video in *; do
    if [[ -f "$video" ]]; then
    filename="${video%.*}"
    extension="${video##*.}"
    mkdir "$dir"/"$filename"
    dest="$dir"/"$filename"
    
  4. Find any frames that are 9/10 different than the frame before and save the time to a txt file.

    ffprobe -show_frames -of compact=p=0 -f lavfi "movie="$video",select=gt(scene\,0.9)" -show_entries frame=best_effort_timestamp_time > tmp.txt
    
  5. Clean up and replace text file.

    sed -e 's/.*best_effort_timestamp_time=\(.*\)|tag:lavfi.scene_score.*/\1/' tmp.txt > chapter.txt
    rm tmp.txt
    
  6. Create array variable from the text file times.

    file=chapter.txt
    while read line
    do
        time+=($line)   
    done <"$file"
    
  7. Cut video between the two black frames.

    ffmpeg -i "$video" -ss "${time[0]}" -to "${time[1]}" "$dest"/middle-"$filename"."$extension"
    
  8. Delete no longer needed text file and end.

    rm chapter.txt
    fi
    done
    
2
  • Hmm... I'm getting a "mkdir: /output: Permission denied mkdir: /output: No such file or directory" error. (I will try using my brother - who knows the command line well - to get past this part.) Jul 11, 2018 at 17:17
  • Since it appears to be a permissions issue, try running it under Sudo
    – aclab28
    Jul 12, 2018 at 1:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.