I have been recently introduced to the world of bash scripting. I currently have a video of file which I want to grep the duration. The problem is assigning the duration value to a variable. I get the errors shown below. What is the best way to assign duration value to a variable? Also is it necessary to have two greps. For example the first grep gives duration=171.805000
, Then i have to do a second grep for the decimal value only.
snippet
#!/bin/bash/
str_duration=echo$(ffprobe -i "media/myvideo.mp4" -show_format -v quiet | grep duration)
int_duration=echo ${str_duration} | grep -o ' [0-9]\+\.[0-9]\+'
error
line 15: echoduration=171.805000: command not found
command output
ffprobe version git-2014-12-27-d4fd3f2 Copyright (c) 2007-2014 the FFmpeg developers
built on Dec 27 2014 12:23:47 with gcc 4.8 (Ubuntu 4.8.2-19ubuntu1)
configuration: --enable-gpl --enable-libfaac --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-librtmp --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libx264 --enable-nonfree --enable-version3
libavutil 54. 15.100 / 54. 15.100
libavcodec 56. 19.100 / 56. 19.100
libavformat 56. 16.102 / 56. 16.102
libavdevice 56. 3.100 / 56. 3.100
libavfilter 5. 6.100 / 5. 6.100
libswscale 3. 1.101 / 3. 1.101
libswresample 1. 1.100 / 1. 1.100
libpostproc 53. 3.100 / 53. 3.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/media/myvideo.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf56.16.102
Duration: 00:02:51.81, start: 0.000333, bitrate: 1504 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 1367 kb/s, 29.97 fps, 29.97 tbr, 30k tbn, 59.94 tbc (default)
Metadata:
handler_name : VideoHandler
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 127 kb/s (default)
Metadata:
handler_name : SoundHandler
duration=171.805000
Try something like:
str_duration=$(ffprobe -i "media/myvideo.mp4" -show_format -v quiet | grep duration | awk -F'=' '{print $2}')
You dont need echo. Also the output generated by your command is:
duration=171.805000
And you need to assign numbers to str_duration variable and hence with awk you get numbers whatever is after "=".
So... To answer your question about the error, you need a space after the echo
command.
But wait, there's more.
You probably don't really want the word "echo" as part of your duration variable. You'd use echo to display output of some kind, not to gather data and store it in a variable. Variable assignments are in the form of variable=value
or read variable
which can take a value from a variety of sources.
Note that without the -v quiet
, the ffprobe command will dump a plethora of data to stderr
, so it's important to include it to reduce the noise of your script.
The output of your (quieted) ffprobe
command would include something like this:
duration=171.805000
You can do a number of things with this format of data (my goodness, it looks like variable=value
...), but the easiest might be to use cut
.
file="media/myvideo.mp4"
str_duration=$(ffprobe -i "$file" -show_format -v quiet | grep ^duration | cut -d= -f2)
Note that this approach of using the equals as a field separator might fail for other fields which might include their own equals sign. But it should be safe for duration.
Alternately, you could use tools like awk
or sed
to reduce the number of pipes:
str_duration=$(ffprobe -i "$file" -show_format -v quiet | sed -ne '/^duration=/s///p')
or
str_duration=$(ffprobe -i "$file" -show_format -v quiet | awk -F= '$1=="duration"{print $2}')
I am purposely not going to tell you how to use the eval
command to take ffprobe's output and assign it directly as a variable within your script, because the eval
command is very dangerous if you don't check and limit its input. As a beginning shell programmer, you should read about eval
and then not use it until you feel that you're somewhere between "intermediate" and "advanced". :)
Alternately, you can use Input Field Separators to parse this data in bash:
declare -A details
while IFS== read field value; do
details[$field]="$value"
done < <(ffprobe -i "$file" -show_format -v quiet | grep '.=.')
echo "${details[duration]}"
This takes the output of the ffprobe command and commits it to the elements of an array, which you can read as per the echo
line. It is safe for content that includes an equals sign, because of the limited number of variables mentioned in the read
command.
Note that except in the case of this last example, ALL the commands in this answer are compatible with traditional /bin/sh, not just bash.
I would go with:
duration=$( ffprobe -i "media/myvideo.mp4" -show_format -v quiet | grep duration | sed 's/.*=//g' )
If you wanted 'just' the number:
duration=$( ffprobe -i "media/myvideo.mp4" -show_format -v quiet | grep ^duration | sed -e 's/.*=//' -e 's/\..*//' )
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.