Reputation: 1315
I have a text file that contains frame numbers line by line and I am using a bash script and ffmpeg to cycle through each line and attempt to print out a thumbnail of each frame.
Each time I run the bash script in my terminal it halts with an error having created the first thumbnail. It seems it is not given the thumbnail a unique name. What am I doing wrong?
My bash script:
#!/bin/bash
source text.txt
while read name
do
ffmpeg -i result.mp4 -vf "setpts=N+1,select='eq(n,$name)'" -vframes 1 frames-$i.jpg
done <text.txt
The error:
File 'frames-.jpg' already exists. Overwrite ? [y/N] Not overwriting - exiting
Upvotes: 2
Views: 675
Reputation: 4822
First, I am guessing you are not needing to source
the file text.txt in your script. When a file is sourced by source filename
or . filename
the lines of code in the file are executed as if they were printed at the command line. As such, I have removed this section of your script.
Second, as noted by others you did not define or update a $i
variable. A modification as such might work for you:
#!/bin/bash
i="0"
while read -r name || [[ -n "${name}" ]]; do # allows for last line with no newline
ffmpeg -i result.mp4 -vf "setpts=N+1,select='eq(n,${name})'" -vframes 1 frames-${i}.jpg
if [ "$?" -eq "0" ]; then
printf -- 'ffmpeg succeeded - creating frames-%s.jpg for %s\n' "${i}" "${name}"
else
printf -- 'ffmpeg failed - was unable to create frames-%s.jpg for %s\n' "${i}" "${name}"
fi
let i+="1"
done <text.txt
Some additional notes on the script above:
It is recommended to use -r
with read
to disable interpretation of backslash escapes and line-continuation in the data read. This can keep you from a plague of issues if your input ever has bash
escapable characters.
I added || [[ -n "${name}" ]]
to the while condition to allow for the last line in your input file to not have a newline as the last character. Otherwise the last line will be ignored by the standard read process as it requires a newline character at the end of each line.
I added a check of the bash builtin variable $?
. The return value of the previous command is stored in $?
. 0
indicates success, others indicates error.
EDIT
If you want to help troubleshoot what ffmpeg is doing, you can try the following modified script:
#!/bin/bash
set -x # activate bash debugging output
while read -r frame_number || [[ -n "${frame_number}" ]]; do # allows for last line with no newline
ffmpeg -i result.mp4 -vf "setpts=N+1,select='eq(n,${frame_number})'" -vframes 1 frames-${frame_number}.jpg
if [ $? -eq 0 ]; then
printf -- 'ffmpeg succeeded - creating frames-%s.jpg\n' "${frame_number}"
else
printf -- 'ffmpeg failed - was unable to create frames-%s.jpg\n' "${frame_number}"
fi
done <text.txt
The edits include:
bash
debugging by adding set -x
.Using the modified script above you should be able to see all the output from ffmpeg
each time it runs. My mock tests show that all should be functioning correctly per your desired outcomes. Can you test again and report back your findings?
Upvotes: 2
Reputation: 22428
Try defining $i
:
i=0
while read name
do
((i++))
ffmpeg -i result.mp4 -vf "setpts=N+1,select='eq(n,$name)'" -vframes 1 frames-$i.jpg
done <text.txt
Upvotes: 1