Part of my new ffmpeg
toolbox are some utility scripts
that I want to present in this article.
- Display Video Properties
- Extract Image at Time
- Calculate Duration of Videos in a Folder
- Output Key-Frame Times
All scripts would output their syntax and exit when called without command line arguments.
Display Video Properties
videoProperties.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | ####################################################### # Displays quality settings of video and audio. ####################################################### [ -z "$1" -o -d "$1" ] && { echo "SYNTAX: $0 [-a|videoPropertyCsv] videoFile [videoFile ...]" >&2 echo "Shows significant properties of first video and audio stream." >&2 echo "-a: show full property listing" >&2 echo "videoPropertyCsv: comma-separated list of video properties to show" >&2 exit 1 } formatProperties() { # $1 = properties CSV, $2 = video file ffprobe -v error \ -show_entries format=$1 \ -of default=noprint_wrappers=1 $2 \ | sort \ | uniq \ | sed 's/^/format /' } streamProperties() { # $1 = properties CSV, $2 = stream of property, $3 = video file ffprobe -v error \ -select_streams $2 -show_entries stream=$1 \ -of default=noprint_wrappers=1 $3 \ | sort \ | uniq \ | sed 's/^/'$2' /' } displayVideoProperties() { # $1 = video file videoFile=$1 echo "Properties for $videoFile" >&2 if [ -n "$propertyList" ] then streamProperties $propertyList v:0 $videoFile elif [ "$showAll" = "true" ] then ffprobe -v error -show_format -show_streams $videoFile else formatProperties format_name,bit_rate $videoFile streamProperties codec_name,profile,time_base,pix_fmt,avg_frame_rate,r_frame_rate,width,height,bit_rate v:0 $videoFile streamProperties codec_name,sample_rate,channels,bit_rate a:0 $videoFile fi } for argument in $* do if [ -f "$argument" ] then displayVideoProperties $argument elif [ "$argument" = "-a" ] then showAll=true else propertyList=$argument fi done |
For every given video file, it would output the most important quality properties, prepending "format" for general, "v:0" for video and "a:0" for audio, so that we can see where the property belongs to. If you give one or more property names (comma-separated without spaces), it would restrict the output to video-stream properties of that name (just the first video of possibly several).
The option -a
("all") would cause a
full output of all stream- and format- properties.
Mind that there could be also programs and subtitles inside the video.
Examples:
videoProperties.sh testvideos/GOPR1486.MP4 format bit_rate=30137653 format format_name=mov,mp4,m4a,3gp,3g2,mj2 v:0 bit_rate=30005060 v:0 codec_name=h264 v:0 height=1080 v:0 pix_fmt=yuvj420p v:0 profile=High v:0 r_frame_rate=48000/1001 v:0 time_base=1/48000 v:0 width=1920 a:0 bit_rate=128013 a:0 channels=2 a:0 codec_name=aac a:0 sample_rate=48000
videoProperties.sh start_time,duration testvideos/GOPR1486.MP4 v:0 duration=26.797604 v:0 start_time=0.000000
Extract Image at Time
extractImage.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ####################################################### # Extracts an image from given video at given time. ####################################################### IMAGEFILENAME=image.png [ -z "$1" -o ! -f "$1" -o -z "$2" ] && { echo "SYNTAX: $0 videoFile time [imageFilePath]" >&2 echo "Extracts an image from a video to default image file $IMAGEFILENAME" >&2 echo "Example:" >&2 echo " $0 myvideo.mp4 1:23 title-image.png" >&2 echo " would extract the key-frame image at or before minute 1 second 23" >&2 echo " from myvideo.mp4 to title-image.png." >&2 exit 1 } video=$1 time=$2 image=${3:-$IMAGEFILENAME} ffmpeg -y \ -ss $time -i $video -frames:v 1 \ -f image2 $image |
First argument is the video file, second the time when the targeted image occurs, optional third the name of the resulting image file.
The ffmpeg
command uses
input-seeking (-ss before -i),
thus it would find a key-frame at, or shortly before, given time.
Mind that you can also specify
thousands seconds by adding ".111" to seconds.
Calculate Duration of Videos in a Folder
durationOfVideos.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | ####################################################### # The rounded duration of all videos in given directory. ####################################################### [ -z "$1" ] && { echo "SYNTAX: $0 videoDir" >&2 exit 1 } cd $1 || exit 2 sum=0 for video in `ls -1 *.MP4 *.mp4 2>/dev/null | sort` do seconds=`ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 \$video` sum=`echo "\$sum \$seconds" | awk '{ print $1 + $2 }'` echo "$video: $seconds seconds" >&2 done echo "sum of seconds = $sum" >&2 rounded=`echo \$sum | awk '{ print int($1 + 0.5) }'` hours=`expr \$rounded / 3600` rest=`expr \$rounded % 3600` minutes=`expr \$rest / 60` seconds=`expr \$rest % 60` echo "$hours:$minutes:$seconds" |
This script specializes on MP4 files. If you have others, replace the ls -1
wildcard patterns in line 13.
It changes to the given video directory, loops all videos and displays their duration in seconds on stderr
.
Finally it displays the rounded sum in hours:minutes:seconds format on stdout
.
Because bc
("binary calculator") is not installed on every UNIX system,
I use awk
for calculations. It processes decimal numbers precisely,
while the expr
("expression") command can process only integers.
Example:
durationOfVideos.sh testvideos
20200905_133128.mp4: 44.139000 seconds
GOPR1486.MP4: 26.816000 seconds
GOPR1487.MP4: 26.901333 seconds
GOPR1488.mp4: 29.802667 seconds
TITLE.MP4: 7.007000 seconds
sum of seconds = 134.666
0:2:15
Output Key-Frame Seconds
keyFrameSeconds.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | ########################################### # Outputs the seconds when key-frames occur. ########################################### [ -f "$1" ] || { echo "SYNTAX: $0 videoFile" >&2 echo "Outputs the times when key-frames occur in given video." >&2 exit 1 } ffprobe -v error \ -select_streams v:0 \ -skip_frame nokey \ -show_frames -show_entries frame=pkt_pts_time \ -of default=noprint_wrappers=1:nokey=1 \ $1 |
This script my be useful when you want to know where the key-frames are in your video.
Example:
keyFrameSeconds.sh testvideos/GOPR1486.MP4 0.000000 0.500500 1.001000 1.501500 2.002000 2.502500 3.003000 3.503500 4.004000 4.504500 5.005000 5.505500 6.006000 6.506500 7.007000 7.507500 8.008000 8.508500 9.009000 9.509500 10.010000 10.510500 11.011000 11.511500 12.012000 12.512500 13.013000 13.513500 14.014000 14.514500 15.015000 15.515500 16.016000 16.516500 17.017000 17.517500 18.018000 18.518500 19.019000 19.519500 20.020000 20.520500 21.021000 21.521500 22.022000 22.522500 23.023000 23.523500 24.024000 24.524500 25.025000 25.525500 26.026000 26.526500
This shows that in given video there is a key-frame every half a second.
Keine Kommentare:
Kommentar veröffentlichen