Once I start this convertscript.sh I want it to constantly check the files in the directory, if theres an .mkv it will convert it which it does fine at the moment, but when there are no mkv files left it seems to exit out the script, but I want it to loop and keep trying the script constantly.
Basically if a new file gets added say during the night because the script is looping constantly it picks it up, I don't want to run the convertscript.sh again. I want to run convertscript.sh once initially and then not touch it.
The script I've got so far is below:
shopt -s globstar
for f in **/*.mkv
do
ffmpeg -i "$f" -c:v libx264 -preset ultrafast -minrate 4.5M -maxrate 4.5M -bufsize 9M -c:a ac3 "${f%mkv}mp4";
[[ $? -eq 0 ]] && rm "$f";
done
If you want to loop forever, you have to say so.
shopt -s globstar
while true; do
for f in **/*.mkv; do
ffmpeg -i "$f" -c:v libx264 -preset ultrafast \
-minrate 4.5M -maxrate 4.5M -bufsize 9M \
-c:a ac3 "${f%mkv}mp4" &&
rm "$f"
done
# Don't consume CPU by looking for new files immediately
sleep 1
done
Notice also how we avoid the $? antipattern. Maybe increase the sleep to five minutes or so once you are confident that this is working as planned.
Related
I'd like to convert all .mp4 movies in a folder and delete the old one afterwards.
Does anyone have a hint? I've been trying for hours.
The only thing I found is:
How to make ffmpeg delete the original file after changing containers? (using a send to bat file)
my idea:
ffmpeg -i *.mp4 -c:v libx264 -b:v 1.5M -c:a aac *.mp4
It asks if files can be overwritten, but then it doesn't:https://pastebin.com/tJtWpm2n
In ffmpeg you can't directly write to the same file you're currently reading from, but one thing you can do instead is write to a temporary file, then replace the original if ffmpeg converted successfully.
for f in *.mp4; do
ffmpeg -i "${f}" -c:v libx264 -b:v 1.5M -c:a aac "tmp_${f}" && mv "tmp_${f}" "${f}"
done
So ffmpeg reads from variable ${f} containing the original filename matched in the *.mp4 pattern and writes to tmp_${f}, then && tests ffmpeg exited successfully before replacing the original file with mv.
You might also want to ensure "tmp_${f}" does not exist first, which only takes a few more steps.
for f in *.mp4; do
tmpf=$(mktemp -p ./ -t "tmp.XXXXXXXXXX.${f##*.}") # can now be extended for any file extension
ffmpeg -i "${f}" -c:v libx264 -b:v 1.5M -c:a aac "${tmpf}" && mv "${tmpf}" "${f}"
done
simple BASH script:
for i in *; do
ffmpeg -i "$i" -vcodec copy -acodec aac "${i/%.*}_AAC.mp4"
rm "$i"
done
i'd like to modify this so as to ignore .srt files, and any other extension other than the standard video ones. if possible, i'd also like it to traverse subdirectories, but i think i can just ls -R | <script> and that should do it. can i replace the '*' with a RegEx? i'm posting from mobile, so i can't test any of this out until i tonight.
EDIT: i am running this in BASH as a script. i will be compiling ffmpeg with x265 encoding support later, so i expect i'll be re-running this script once i have that done.
In bash 4 this will recurse subdirectories below current directory and work on 4 extensions- avi, mp4, mpg, mpeg. You can add more if you like.
shopt -s globstar nullglob dotglob
for file in ./**/*.{mpg,mpeg,mp4,avi}
do
ffmpeg -i "$file" -c:a aac -b:a 128k -c:v libx264 -pix_fmt yuv420p \
-crf 22 -refs 1 -bf 0 -coder 0 -g 25 -keyint_min 15 -movflags +faststart \
${file%.*}_converted.mp4
done
The added parameters are as a sample of what is possible to use. You can set your own -crf, threads etc.
I have a simple script that loops through files in a folder and then converts them from flv to mp4. How in bash do I skip over the files in the folder that have a fcntl lock on them and then come back when the lock is removed?
#!/bin/bash
for file in /video_recordings/stream/*.flv; do
today=`date '+%Y_%m_%d_%H_%M_%S'`;
cp -v "$file" /video_recordings/stream/backups/$today.flv;
[ -e "${file%.flv}".mp4 ] || ffmpeg -threads 1 -i "$file" -c:v libx264 -c:a aac -b:v 768k -b:a 96k -vf "scale=720:trunc(ow/a/2)*2" -tune fastdecode -preset ultrafast -crf 25 /video_recordings/stream/temp/$today.mp4
cp -v /video_recordings/stream/temp/$today.mp4 /video_recordings/stream/vod/$today.mp4
rm /video_recordings/stream/temp/$today.mp4
sleep 15s;
rm "$file";
done
I don't know much about fcntl, but according to this answer such locks should be listed by fuser. If something is accessing a file fuser exits with status code 0 and 1 otherwise.
To come back to the locked files later use an array as if it was a queue:
#!/bin/bash
queue=(/video_recordings/stream/*.flv)
while (( ${#queue[#]} > 0 )); do
file="${queue[0]}"
queue=("${queue[#]:1}")
if fuser -s "$file"; then
echo "$file in use. Try later."
queue+=("$file")
continue
fi
# insert commands for conversion of `$file` here
done
This question already has answers here:
bash script order of execution
(2 answers)
Closed 7 years ago.
I will be on 3 days vacation, so I would like to do a task in one file, after it's done, launch the other one using bash script, the way I would like to do is:
List files location in one file, i.e (toDo.txt)
Once the first file is done it goes to the other one.
Example:
doDo.txt contents:
/home/me/www/some_dir/file1F42.sh
/home/me/www/another_dir/fileD2cD.sh
/home/me/www/third_dir/fileG0IU.sh
/home/me/www/last_dir/fileVFpO.sh
file1F42.sh:
some commands here
Once is done, it should jump to line 2, which is: fileD2cD.sh
I do NOT want to use cron, because I do not know when the files will finish treatment, and at the same time I do NOT want to launch all of them at once.
This is a real example that I just finish to do:
ffmpeg -i Original/$domainName"_"$fileName"_"$f-Original.mp4 -strict experimental -vf "drawtext=fontfile='/usr/share/fonts/truetype/freefont/FreeSansBold.ttf':text='www.alfirdaous.com':x="$SizeX":y="$SizeY":fontsize="$textSize":fontcolor=$textColor" -vcodec libx264 -preset medium -crf 24 -acodec copy Done/"$domainName"_"$fileName"_$f-Done.mp4
mp4Box=$(MP4Box -add Done/"$domainName"_"$fileName"_$f-Done.mp4 "$domainName"_"$fileName"_$f.mp4)
echo $mp4Box >> ffmpeg_exec.log;
# Delete Done files
rm Done/"$domainName"_"$fileName"_$f-Done.mp4
# Get master thumbnail
ffmpeg -itsoffset -150 -i "$domainName"_"$fileName"_$f.mp4 -vcodec mjpeg -vframes 1 -an -f rawvideo -s 640x480 "$silsilaName"_$f.png
n=0
for offset in 140 160 180 200 220 240 260 280 300 320
do
printf -v outfile "$silsilaName"_"$f"_"%03d.png" "$((++n))"
ffmpeg -itsoffset -$offset -i $domainName"_"$fileName"_"$f.mp4 -vcodec mjpeg -vframes 1 -an -f rawvideo -s 640x480 "$outfile"
done
ffmpeg -i "$domainName"_"$fileName"_$f.mp4 -vn -ar 44100 -ac 2 -ab 128 -f mp3 $f.mp3
done
Last command line is:
ffmpeg -i "$domainName""$fileName"$f.mp4 -vn -ar 44100 -ac 2 -ab 128 -f mp3 $f.mp3
How do I know that it is DONE, finish, so I can go to my file list "doDo.txt" and start running the next file?
#! /bin/sh
while read file; do
echo "Executing $file"
sh "$file"
done < /dev/stdin
Where usage is <script.sh> < file_list
I have a pretty simple shell script and after doing the first two jobs, it just stops and sits there, doesnt do anything, it doesnt seem to matter what the third job is, if I switch the order etc, it will not finish it.
Any ideas would be great...
Here is my shell script
for f in "$#"
do
name=$(basename "$f")
dir=$(dirname "$f")
/opt/local/bin/ffmpeg -i "$f" -y -b 250k -deinterlace -vcodec vp8 -acodec libvorbis -nostdin "$dir/webm/${name%.*}.webm"
/opt/local/bin/ffmpeg -i "$f" -y -b 250k -strict experimental -deinterlace -vcodec h264 -acodec aac -nostdin "$dir/mp4/${name%.*}.mp4"
/opt/local/bin/ffmpeg -i "$f" -y -ss 00:00:15.000 -deinterlace -vcodec mjpeg -vframes 1 -an -f rawvideo -s 720x480 "$dir/img/${name%.*}.jpg"
done
Your final ffmpeg line needs -nostdin.
Running FFMPEG from Shell Script /bin/sh