Launch a file script after the first one is done [duplicate] - bash

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

Related

ffmpeg - set variable video duration

I use this command to convert files in batch plus crop and re-scale:
for i in $( ls *.mp4 ); do
ffmpeg -y -i "$i" -acodec libfaac -ab 128k -ar 44100 -vcodec libx264 -b 850k -threads 0 -vf [in]crop=in_w-112:in_h-63:56:0,scale=1280:720[out] "../../archive/${i/.mp4/}.mp4"
done
this command will start at second 15, and makes video 30 seconds long:
for i in $( ls *.mp4 ); do
ffmpeg -ss 00:00:15 -t 30 -y -i "$i" -acodec libfaac -ab 128k -ar 44100 -vcodec libx264 -b 850k -threads 0 -vf [in]crop=in_w-112:in_h-63:56:0,scale=1280:720[out] "${i/.mp4/}_test.mp4"
done
what I would like is a command that cuts off 15s from the beginning and 15s from the end of EACH video from the BATCH ... the trick is that each video has different duration, so "how long it is" must be a variable (duration minus 15s or minus 30s if I count 15s from the start as well)
video duration examples:
video 1 - 00:25:19
video 2 - 00:15:34
video 3 - 00:19:21
video 4 - 00:22:49
etc.
Couldn't you do this with a simple bash script?
As stated here this command will retrieve the video duration in seconds:
ffprobe -i some_video -show_entries format=duration -v quiet -of csv="p=0"
So you can read that into a variable, then simply withdraw 30 seconds and you will now what duration to set in your ffmpeg command.
So, step 1 will be the first for-loop you have already posted in your question.
Step 2 will be to withdraw 30 seconds from the movies duration and save that in a variable.
Then in step 3, rewrite your second for-loop like this:
for i in $( ls *.mp4 ); do
ffmpeg -ss 00:00:15 -t $your_new_duration_variable -y -i "$i" -acodec libfaac -ab 128k -ar 44100 -vcodec libx264 -b 850k -threads 0 -vf [in]crop=in_w-112:in_h-63:56:0,scale=1280:720[out] "${i/.mp4/}_test.mp4"
done

appending a string constant selectively within a while loop in bash

I have a script called automateutube that I edit in VIM and execute in the terminal with sh ./automateutube.sh This script pulls youtube links from a file called songs.txt and downloads the video from youtube then extracts the audio.
The songs.txt file looks like this
https://www.youtube.com/watch?v=IxQOlZ3pqtI
https://www.youtube.com/watch?v=IxQOlZ3pqtI
https://www.youtube.com/watch?v=IxQOlZ3pqtI
https://www.youtube.com/watch?v=IxQOlZ3pqtI
It is just a bunch of links, one per line.
The script looks like this
#!/bin/bash
while read p; do
x=/tmp/.youtube-dl-$(date +%y.%m.%d_%H.%M.%S)-$RANDOM.flv
youtube-dl --audio-quality 160k --output=$x --format=18 "$p"
ffmpeg -i $x -acodec libmp3lame -ac 2 -ab 128k -vn -y "$p"
rm $x
done <songs.txt
Now the first part executes. It downloads the video and starts to unpack it.
It is the second part that fails. ffmpeg -i $x -acodec libmp3lame -ac 2 -ab 128k -vn -y "$p"
This is because "$p" is supposed to be in format "filename.mp3" However as it is p takes the value of a youtube link, without ".mp3" appended.
This works for the first line
youtube-dl --audio-quality 160k --output=$x --format=18 "$p"
because "$p" is supposed to be in the form of a link there.
Now I have tried adding three lines in
a="$.mp3"
b="$p"
c=$b$a
and making ffmpeg -i $x -acodec libmp3lame -ac 2 -ab 128k -vn -y "$p"
into ffmpeg -i $x -acodec libmp3lame -ac 2 -ab 128k -vn -y "$c"
but I am still getting an error. Any ideas?
parse error, at least 3 arguments were expected, only 1 given in string 'om/watch?v=sOAHOxbMOJY'
So after some experimentation using advice from the comments, I came to this, which works.
#!/bin/sh
while read -r p; do
x=/tmp/.youtube-dl-$(date +%y.%m.%d_%H.%M.%S)-$RANDOM.flv
youtube-dl --audio-quality 160k --output="$x" --format=18 "$p"
SUBSTRING=$(echo "$p"| cut -c33-50)
ffmpeg -i "$x" -acodec libmp3lame -ac 2 -ab 128k -vn -y "$SUBSTRING.mp3" </dev/null
rm "$x"
done <songs.txt
What this fixes is keeping /'s out of the file name, and eliminating parser error.

ffmpeg: Transcoding multiple input files to multiple output files with single command

I want to convert three files with a single command. I used the following command:
-i "C:\fil1.mp4" -i "C:\file2.mp4" -i "C:\file3.mp4" -acodec libmp3lame -ab 32k -ar 22050 -ac 2 -b:v 128k -r 20 -s 176x144 -y file1.mp4 -acodec libmp3lame -ab 32k -ar 22050 -ac 2 -b:v 128k -r 20 -s 176x144 -y file2.mp4 -acodec libmp3lame -ab 32k -ar 22050 -ac 2 -b:v 128k -r 20 -s 176x144 -y file3.mp4
but it converts the first files with names fil1.mp4, fil2.mp4, fil3.mp4 but I want all files should be convert with its output file names.
Using -map helps with specifying which input goes with which output.
I used this code to convert multiple audio files:
ffmpeg -i infile1 -i infile2 -map 0 outfile1 -map 1 outfile2
also use -map_metadata to specify the metadata stream:
ffmpeg -i infile1 -i infile2 -map_metadata 0 -map 0 outfile1 -map_metadata 1 -map 1 outfile2
I wrote bash script for it.
You can modify as you want:
#!/bin/sh
BASE_DIR=$HOME/Videos/mov
OUTPUT_DIR=$BASE_DIR/avi
FILES=$(ls $BASE_DIR | grep .MOV)
for FILE in $FILES
do
FILENAME="${FILE:0:-4}"
ffmpeg -i $BASE_DIR/$FILE $OUTPUT_DIR/$FILENAME.avi
done
I have tried David Blum's script, there was a problem with spaces in filenames. Here's my modified script that uses basename to remove the file extension from filenames. It operates on the current directory, assuming a subdirectory called 'avi':
#!/bin/sh
OUTPUT_DIR=./avi
#IFS=$'\n' # split only on newlines
for FILE in *MOV
do
FILENAME=`basename "${FILE}" .MOV`
ffmpeg -i "$FILE" "$OUTPUT_DIR/$FILENAME.avi"
#echo $FILENAME
done
find ./ -name "*.wav" -exec ffmpeg -i {} -c:a libopus {}.opus \;
Maybe you could try using Different parallel outputs as in the FFMPEG documentation ?
When I have more files to work, I create a spreadsheet sheet and I do the command with "holes".
Every hole match to a file (filename).
I copy/paste in a file which become a script.
I know it is not perfect bet if it can help you.

shell script ffmpeg stops after 2 jobs

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

ffmpeg output to multiple files simultaneously

What format/syntax is needed for ffmpeg to output the same input to several different "output" files? For instance different formats/different bitrates? Does it support parallelism on the output?
The ffmpeg documentation has been updated with lots more information about this and options depend on the version of ffmpeg you use: http://ffmpeg.org/trac/ffmpeg/wiki/Creating%20multiple%20outputs
From FFMpeg documentation, FFmpeg writes to an arbitrary number of output "files".
Just make sure each output file (or stream), is preceded by the proper output options.
I use
ffmpeg -f lavfi -re -i 'life=s=300x200:mold=10:r=25:ratio=0.1:death_color=#C83232:life_color=#00ff00,scale=1200:800:flags=16' \
-f lavfi -re -i sine=frequency=1000:sample_rate=44100 -pix_fmt yuv420p \
-c:v libx264 -b:v 1000k -g 30 -keyint_min 60 -profile:v baseline -preset veryfast -c:a aac -b:a 96k \
-f flv "rtmp://yourname.com:1935/live/stream1" \
-f flv "rtmp://yourname.com:1935/live/stream2" \
-f flv "rtmp://yourname.com:1935/live/stream3" \
Is there any reason you can't just run more than one instance of ffmpeg? I've have great results with that ...
Generally what I've done is run ffmpeg once on the source file to get it to sort of the base standard (say a higher quality h.264 mp4 file) this will make sure your other jobs will run more quickly if your source file has any issues since they'll be cleaned up in this first pass
Then use that new source/input file to run x number of ffmpeg jobs, for example in bash ...
Where you see "..." would be where you'd put all your encoding options.
# create 'base' file
ffmpeg -loglevel error -er 4 -i $INPUT_FILE ... INPUT.mp4 >> $LOG_FILE 2>&1
# the command above will run and then move to start 3 background jobs
# text output will be sent to a log file
echo "base file done!"
# note & at the end to send job to the background
ffmpeg ... -i INPUT.mp4 ... FILENAME1.mp4 ... >/dev/null 2>&1 &
ffmpeg ... -i INPUT.mp4 ... FILENAME2.mp4 ... >/dev/null 2>&1 &
ffmpeg ... -i INPUT.mp4 ... FILENAME3.mp4 ... >/dev/null 2>&1 &
# wait until you have no more background jobs running
wait > 0
echo "done!"
Each of the background jobs will run in parallel and will be (essentially) balanced over your cpus, so you can maximize each core.
based on http://sonnati.wordpress.com/2011/08/30/ffmpeg-–-the-swiss-army-knife-of-internet-streaming-–-part-iv/ and http://ffmpeg-users.933282.n4.nabble.com/Multiple-output-files-td2076623.html
ffmpeg -re -i rtmp://server/live/high_FMLE_stream -acodec copy -vcodec x264lib -s 640×360 -b 500k -vpre medium -vpre baseline rtmp://server/live/baseline_500k -acodec copy -vcodec x264lib -s 480×272 -b 300k -vpre medium -vpre baseline rtmp://server/live/baseline_300k -acodec copy -vcodec x264lib -s 320×200 -b 150k -vpre medium -vpre baseline rtmp://server/live/baseline_150k -acodec libfaac -vn -ab 48k rtmp://server/live/audio_only_AAC_48k
Or you could pipe the output to a "tee" and send it to "X" other processes to actually do the encoding, like
ffmpeg -i input - | tee ...
which might save cpu since it might enable more output parallelism, which is apparently otherwise unavailable
see http://ffmpeg.org/trac/ffmpeg/wiki/Creating%20multiple%20outputs and here
I have done like that
ffmpeg -re -i nameoffile.mp4 -vcodec libx264 -c:a aac -b:a 160k -ar 44100 -strict -2 -f flv \
-f flv rtmp://rtmp.1.com/code \
-f flv rtmp://rtmp.2.com/code \
-f flv rtmp://rtmp.3.com/code \
-f flv rtmp://rtmp.4.com/code \
-f flv rtmp://rtmp.5.com/code \
but is not working completely well as i was expecting and having on restream with nginx

Resources