5

I'm using this bash script to generate thumbnails from videos:

#!/bin/bash
source_dir="."
output_dir="/output"
input_file_types=(avi wmv flv mkv mpg mp4)
output_file_type="jpg"
r1=$(( ( RANDOM % 10 )  + 5 ))

convert() {
        echo "" | ffmpeg -ss 00:"r1":05 -y -i "$1" -an -f image2 -vframes 1 "$output_dir/$2"
}

for input_file_type in "${input_file_types[@]}"
do
        find "$source_dir" -name "*.$input_file_type" -print0 | while IFS= read -r -d $'\0' in_file
        do
                echo "Processing…"
                echo ">Input  $in_file"

                # Replace the file type
                out_file=$(echo "$in_file" | sed "s/\(.*\.\)$input_file_type/\1$output_file_type/g")
                # The above can be shortened to
                # out_file="${in_file%.$input_file_type}.$output_file_type"
                echo ">Output $out_file"

                # Convert the file
                convert "$in_file" "$out_file"

                if [ $? != 0 ]
                then
                    echo "$in_file had problems" >> handbrake-errors.log
                fi

                echo ">Finished $out_file\n\n"
        done
done
echo "DONE CONVERTING FILES"

What I want is to calculate the total video time and generate a thumbnail from a random video time.

mediainfo myvideo.mp4 | grep Duration
Duration                                 : 5mn 7s
Duration                                 : 5mn 7s
Duration                                 : 5mn 7s

How do I integrate grep Duration into the bash script above so I can get a thumbnail with a random time based on the total video time?

  • I edited your question.  (1) If you’re going to pass arguments to a shell function, you should probably use the arguments rather than having the function access the global variables.  (2) for bars in "${bars[@]}" is not just stylistically confusing; it is like saying for bars[0] in "${bars[@]}".  Not literally; that’s not syntactically valid; but my point is that it sets bar[0] equal to the last bar[…] value.  After your loop, input_file_types is equal to ( mp4 wmv flv mkv mpg mp4).  … (Cont’d) – G-Man Jul 13 '15 at 19:12
  • (Cont’d) …  That could cause hard-to-debug problems if you ever used "${input_file_types[@]}" again in the script.  (3) You should always quote all shell variable references (e.g., echo ">Input "$in_fileecho ">Input $in_file") unless you have a good reason not to, and you’re sure you know what you’re doing.  (4) Speaking of which, did you mean to say ffmpeg -ss 00:"$r1":05? – G-Man Jul 13 '15 at 19:13
2

Try grabbing the duration in seconds, as this will make everything easier:

Your convert function could end up being:

convert() {
    # Get duration in milliseconds, then convert to seconds
    duration=$(($(mediainfo --Inform="General;%Duration%" "${in_file}" ) / 1000 ))

    # Calculate random time
    random_time=$(date -u -d @$(shuf -i 0-${duration} -n 1) +"%T")

    # Take screenshot
    ffmpeg -ss ${random_time} -i "$in_file" -vframes 1 -q:v 2 "$output_dir/$output_file"
}
  • i got this error Invalid duration specification for ss: -y – juicebyah Jul 13 '15 at 18:12
  • I fixed it up and tested it on my machine. ffmpeg can take the time in seconds, which removes a step. – nrcrast Jul 13 '15 at 18:41
0

this bash will do

#!/bin/bash
source_dir="."
output_dir="."
input_file_types=(avi wmv flv mkv mpg mp4)
output_file_type="jpg"

convert() {
        echo "" | ffmpeg -ss $ss -y -i "$in_file" -an -f image2 -vframes 1 "$output_dir/$out_file"
}

for input_file_types in "${input_file_types[@]}"
do

        find "$source_dir" -name "*.$input_file_types" -print0 | while IFS= read -r -d $'\0' in_file
        do
                echo "Processing…"
                echo ">Input  "$in_file
                # Replace the file type
                out_file=$(echo $in_file|sed "s/\(.*\.\)$input_file_types/\1$output_file_type/g")
                echo ">Output "$out_file

    # get video duration
    fulltime=`ffmpeg -i "$in_file" 2>&1 | grep 'Duration' | cut -d ' ' -f 4 | sed s/,//`;
    hour=`echo $fulltime | cut -d ':' -f 1`;
    minute=`echo $fulltime | cut -d ':' -f 2`;
    second=`echo $fulltime | cut -d ':' -f 3 | cut -d '.' -f 1`;

    seconds=`expr 3600 \* $hour + 60 \* $minute + $second`;
    ss=`expr $seconds / 2`; # from the middle of video

    # Convert the file
                convert "$in_file" "$out_file"

                if [ $? != 0 ]
                then
                    echo "$in_file had problems" >> ffmpeg-errors.log
                fi

                echo ">Finished "$out_file "\n\n"
        done
done

create thumbnail from middle of movie.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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