Bash Script to get info from ffprobe

2019-06-08 09:07发布

问题:

I am trying to create a script to process videos, but I was hoping to get bit_rate, width, and height info from the incoming files so I could better tune the output. The script works when I do the files one at a time, but when I put it into a loop all of a sudden I don't get any info.

So this works:

#!/bin/bash
eval $(ffprobe -v quiet -show_format -of flat=s=_ -show_entries stream=height,width,nb_frames,duration,codec_name input.mp4);
width=${streams_stream_0_width};
height=${streams_stream_0_height};
bitrate=$((${format_bit_rate}/1000));
echo $width,$height,$bitrate;

This doesn't when executed from find ./ -type f -regex ".*\.\(mkv\|mp4\|wmv\|flv\|webm\|mov\|avi\)" -print0 | xargs -0 /root/newbatch.sh

for i; do
eval '$(ffprobe -v quiet -show_format -of flat=s=_ -show_entries stream=height,width,nb_frames,duration,codec_name $i)';
width=${streams_stream_0_width};
height=${streams_stream_0_height};
bitrate=${format_bit_rate};
kbitrate=$((bitrate/1000));
echo $i,$width,$height,$kbitrate;

done

I also get an error with the math of bitrate in the loop, but even when I comment it out I still get no results. Since it works one at a time, I am assuming the problem is a bash scripting and nothing to do with ffmpeg / ffprobe.

That being said, I can do this:

echo $i,$width,$height,$bitrate;

and get back

./file1.mkv,,,
./file2.mkv,,,
./file3.mkv,,,
./file4.mkv,,,

So it does get some info back, but it loses the info from the eval statement.

回答1:

I found the problem was files with whitespaces in the $i variable.

This code combines all the commands into a single shell command that searches the current folder and all subdirectories for all video files, loops though with some options to setup bitrate settings for different resolutions along with some other things to spruce it up.

#!/bin/bash
IFS=$'\n'   

# Reset
Color_Off='\033[0m'       # Text Reset

# Regular Colors
Black='\033[0;30m'        # Black
Red='\033[0;31m'          # Red
Green='\033[0;32m'        # Green
Yellow='\033[0;33m'       # Yellow
Blue='\033[0;34m'         # Blue
Purple='\033[0;35m'       # Purple
Cyan='\033[0;36m'         # Cyan
White='\033[0;37m'        # White

# Bold
BBlack='\033[1;30m'       # Black
BRed='\033[1;31m'         # Red
BGreen='\033[1;32m'       # Green
BYellow='\033[1;33m'      # Yellow
BBlue='\033[1;34m'        # Blue
BPurple='\033[1;35m'      # Purple
BCyan='\033[1;36m'        # Cyan
BWhite='\033[1;37m'       # White

# Underline
UBlack='\033[4;30m'       # Black
URed='\033[4;31m'         # Red
UGreen='\033[4;32m'       # Green
UYellow='\033[4;33m'      # Yellow
UBlue='\033[4;34m'        # Blue
UPurple='\033[4;35m'      # Purple
UCyan='\033[4;36m'        # Cyan
UWhite='\033[4;37m'       # White

# Background
On_Black='\033[40m'       # Black
On_Red='\033[41m'         # Red


VideoFiles=$(find ./ -maxdepth 10 -regex ".*\.\(mkv\|mp4\|wmv\|flv\|webm\|mov\|avi\|m4v\)")  

for i in $VideoFiles  
do  
  filename=$(basename "$i");
  extension="${filename##*.}";
  filename="${filename%.*}";
echo -e "${UGreen}############################################################################################################################################################################${Color_Off}\n";
echo -e "${Color_Off}Getting info of ${BCyan}$i${Color_Off}";

    eval $(ffprobe -v quiet -show_format -of flat=s=_ -show_entries stream=height,width,nb_frames,duration,codec_name -sexagesimal "$i");
    width=${streams_stream_0_width};
    height=${streams_stream_0_height};
    bitrate=${format_bit_rate};
    kbitrate=$((bitrate/1000));
    duration=${format_duration};
    #duration=$((durationSec/60));
    d=$(dirname "$i")
echo -e "${Color_Off}Duration = ${URed}$duration ${Color_Off}, Height/Width = ${URed}$height/$width ${Color_Off} Bitrate =${URed} $bitrate${Color_Off}\n";
echo -e "${UGreen}############################################################################################################################################################################${Color_Off}";
mkdir $d/Processed;

if ((1<= $height &&  $height<=400))
then    
    desired="200k";
    min="100k";
    max="800k";
    echo -e "This is a ${UPurple}LOW Quality${Color_Off} File\n.";

elif ((401<= $height &&  $height<=660))
then
    desired="500k";
    min="200k";
    max="1000k";
    echo -e "This is a ${UPurple}480p${Color_Off} File\n";
elif ((661<= $height &&  $height<=890))
then
    desired="800k";
    min="250k";
    max="1300k";
    echo -e "This is a ${UPurple}720p${Color_Off} File\n";

elif ((891<= $height &&  $height<=1200))
then
    desired="1200k";
    min="350k";
    max="2300k";
    echo -e "This is a ${UPurple}1080p${Color_Off} File\n";
else
    desired="1500k";
    min="550k";
    max="2700k";
    echo -e "This is a ${UPurple}HQ${Color_Off} File\n";
fi
    ffmpeg -n -i "$i" -c:v hevc_nvenc -hide_banner -preset fast -x265-params keyint=33:min-keyint=33 -crf 30 -b:v $desired -minrate $min -maxrate $max -bufsize 25M -c:a copy "$d/X265_$filename.mp4"
mv $i $d/Processed;
done  


标签: bash ffmpeg